C++ 中的 char 数组损坏
我正在开发一个项目,该项目使我存储一个对象数组,其构造函数是
Item(char* item, int itemType){
char temp[200];
for(int i = 0; i < 200; i++){
temp[i] = '\0';
if(item[i] != '\0'){
temp[i] = item[i];
}
}
_item = item;
_itemType = itemType;
_tweetIDs = NULL;
}
“不要担心 _tweetIDs”,这是我程序的另一个功能部分,与我的问题无关。
该数组存储在一个类中:
ItemList()
它的工作原理是我的程序的功能部分解析一行输入并将其放入 Item(char*, int) 对象中。这是它添加行的方式:
int addItem(char* item, int type){
char temp1[200];
for(int i = 0; i < 200; i++){
temp1[i] = '\0';
}
int j = 0;
while(item[j] != '\0'){
temp1[j] = item[j];
j++;
}
_items[_size] = Item(temp1, type);
_size++;
return _size;
}
其中 _items 是 Item() 数组,_size 是每次添加 Item() 时都会递增的字段。
当我必须打印列表的内容时,我的问题就出现了。
我有一个方法可以做到这一点:
void printList(){
for(int i = 0; i < 500; i++){
if(_items[i] != NULL){
cout << "[" << i << "] ";
_items[i]->printContents();
}
}
}
我在 Item() 的构造函数中测试了 printContents() ,并在 addItem 方法中测试了 printList ,它们在类本身内调用时都可以工作。当我必须在类主体之外调用 print 方法时,问题就出现了。
在 main 方法中,我创建一个 List 对象:
List itemList;
默认构造函数将 Item() 数组的所有成员设置为 NULL 并初始化 _size。
在将一些 Item() 对象添加到数组中(我通过调试器确认其大小正在增加)后,我尝试将其打印出来。当我调用时:
itemList.printList();
它给了我正确数量的索引(和行),但 char 数组只是一堆垃圾。我使用调试器尝试找出问题所在。在 addItem() 方法中,我调用 printList 来检查数组,输出结果很好。然后,我在最后一次 addItem() 调用之后立即调用了 itemList.printList() ,它给了我垃圾。在 addItem() 和 itemList.printList() 之间,字符数组丢失或类似的东西。
知道出了什么问题吗?如果您需要的话,我会给您更多代码。
I'm working on a project that makes me store an array of objects whose constructor is
Item(char* item, int itemType){
char temp[200];
for(int i = 0; i < 200; i++){
temp[i] = '\0';
if(item[i] != '\0'){
temp[i] = item[i];
}
}
_item = item;
_itemType = itemType;
_tweetIDs = NULL;
}
Don't worry about _tweetIDs, that's another functional part of my program and isn't related to my problem.
This array is stored within a class:
ItemList()
How this works is that the functional part of my program parses a line of input and puts it into the Item(char*, int) object. This is how it adds the line:
int addItem(char* item, int type){
char temp1[200];
for(int i = 0; i < 200; i++){
temp1[i] = '\0';
}
int j = 0;
while(item[j] != '\0'){
temp1[j] = item[j];
j++;
}
_items[_size] = Item(temp1, type);
_size++;
return _size;
}
Where _items is the Item() array and _size is a field that is incremented every time an Item() is added.
My issue comes when I have to print the contents of the list.
I have a method that does that:
void printList(){
for(int i = 0; i < 500; i++){
if(_items[i] != NULL){
cout << "[" << i << "] ";
_items[i]->printContents();
}
}
}
I tested printContents() in the constructor of Item() and tested printList in the addItem method and they both work when called within the class itself. The issue comes when I have to call the print method outside the class body.
In the main method, I create a List object:
List itemList;
The default constructor sets all members of the Item() array to NULL and initializes _size.
After adding a few Item() objects into the array (Which I confirmed is increasing in size through the debugger), I tried to print it out. When I call:
itemList.printList();
It gives me the right amount of indexes (And lines), but the char array is just a bunch of garbage. I used the debugger to try and find out where it went wrong. In the addItem() method, I called printList to check the array, and the output from that is fine. Then, I called itemList.printList() right after the last addItem() call, and it gave me garbage. In between the addItem() and itemList.printList(), the char array is lost or something along those lines.
Any idea what's going wrong? I'll give you any more code if you need it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在您的
Item
构造函数中,您正在设置我认为是成员_item
的内容:这只是分配
item
指向的位置的指针值代码> 到_item
。它实际上并不复制字符串!下次您去阅读此位置时,它可能是有效的 - 不过,正如您所看到的,它很可能是垃圾。
您正在寻找的是一个类似
strcpy
(顺便说一句,不需要做太多的手动复制 - 只需在Item
构造函数中传递该指针并复制一次即可)。编辑,解决您的评论:
strcpy
使您的程序崩溃,因为您在未分配的内存上使用它。您必须使用
new[ 为数组分配内存]
在 C++ 中In your
Item
constructor, you are setting what I presume is a member_item
as such:This just assigns the pointer value of the location pointed to by
item
into_item
. It does not actually copy the string!The next time you go to read this location, it might be valid - chances are, though, it will be garbage, as you are seeing.
What you are looking for is a function like
strcpy
(as a side note, there's no need to do quite so much manual copying - just pass that pointer around and copy it once - in theItem
constructor).EDIT, to address your comment:
strcpy
made your program crash because you are using it on unallocated memory.You have to allocate memory for an array using
new[]
in c++注意变量的生命周期。
如果将 temp1 声明为静态数组,那么它将在函数 addItem 结束时立即销毁。
最后,所有引用该内存位置的对象都将无效。
和 ....
如果你想传递对数组的引用,可以这样做:
Take note on the lifetime of a variable.
If you declare temp1 as static array, then it will be destroyed immediately by the end of function addItem.
At the end, all object that refers to this memory location will be invalid.
And ....
If you want to pass a reference to an array do it this way:
我想象您对类 Item 的定义至少如下所示:
您的构造函数必须为 _item 分配内存,以便复制通过构造函数传入的内容。如果不这样做将不可避免地导致内存问题和异常。或者,您可以使用诸如 char 向量之类的东西。
I'm imagining your definition of class Item minimally looks like this:
Your constructor must allocate memory for _item in order to make a copy of what gets passed in via the constructor. Failure to do that will inevitable result in memory problems and exceptions. Alternatively, you can use something like a vector of char.
在
Item
构造函数中,您创建本地数组char temp[200]
,然后将char * item
指向的内容复制到那里,然后就不需要了不再使用temp[200]
。这样做有什么意义呢?稍后您将传递的指针分配给
_item
成员。该指针指向addItem()
中的局部变量char temp1[200]
。当addItem()
完成时,temp1
被销毁,因此Item
类中的_item
指向垃圾。您可能需要做的是在
_item
定义中静态分配内存,或者使用new
动态分配内存(然后不要忘记释放它)。我认为第一个解决方案对你来说会更安全。在后一种情况下,您还必须处理复制构造函数和赋值运算符。因此,您需要将_item
定义从char * _item
更改为char _item[200]
,然后就可以使用strncpy< /代码>:
In
Item
constructor you create local arraychar temp[200]
, you copy there what is pointed bychar * item
and then you don't usetemp[200]
any more. What's the point of doing that?Later you assign passed pointer to
_item
member. The pointer points to local variablechar temp1[200]
inaddItem()
. WhenaddItem()
finishes thentemp1
is destroyed and so_item
inItem
class points to garbage.What you probably need to do is to allocate memory either statically in
_item
definition or dynamically usingnew
(and then not forget to release it). I think the first solution will be safer for you. In the latter case you would also have to take care of copy constructor and assign operator. So, you need to change_item
definition fromchar * _item
tochar _item[200]
, and then you can usestrncpy
: