c++中字符数组的损坏

char array corruption in C++

本文关键字:损坏 数组 字符 c++      更新时间:2023-10-16

我正在做一个项目,让我存储一个对象数组,其构造函数是

Item(char* item, int itemType){
char temp[200];
    for(int i = 0; i < 200; i++){
        temp[i] = '';
        if(item[i] != ''){
            temp[i] = item[i];
        }
    }
    _item = item;
    _itemType = itemType;
    _tweetIDs = NULL;
}

不要担心_tweetid,那是我程序的另一个功能部分,与我的问题无关。

这个数组存储在一个类中:

ItemList()

这是如何工作的,我的程序的功能部分解析一行输入并将其放入Item(char*, int)对象。它是这样添加这一行的:

int addItem(char* item, int type){
    char temp1[200];
    for(int i = 0; i < 200; i++){
        temp1[i] = '';
    }
    int j = 0;
    while(item[j] != ''){
        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();

它给了我正确数量的索引(和行),但字符数组只是一堆垃圾。我用调试器试图找出哪里出了问题。在addItem()方法中,我调用了printList来检查数组,结果很好。然后,我在最后一次addItem()调用之后调用itemList.printList(),它给了我垃圾。在addItem()和itemList.printList()之间,字符数组丢失或沿着这些行。

你知道怎么回事吗?如果你需要的话,我可以给你更多的代码。

在您的Item构造函数中,您正在设置我认为是_item成员的内容:

_item = item;

这只是将item所指向位置的指针值赋给_item。它实际上并不复制字符串!

下次读取该位置时,它可能是有效的-尽管有可能是垃圾,正如您所看到的。

你正在寻找的是一个类似strcpy的函数(作为旁注,没有必要做这么多的手动复制-只需传递指针并复制一次-在Item构造函数中)。

编辑,以解决您的评论:

strcpy使你的程序崩溃,因为你在未分配的内存上使用它。

你必须在c++中使用new[]为数组分配内存

注意变量的生存期。如果您声明temp1为静态数组,那么它将在函数addItem结束时立即被销毁。

最后,所有指向该内存位置的对象都将无效。

…如果你想传递一个引用到一个数组,这样做:

Item(char** item, int itemType)

我想象你对class Item的定义至少是这样的:

class Item
{
Item(char* item, int itemType);
private:
    char *_item;
};

构造函数必须为_item分配内存,以便复制通过构造函数传入的内容。如果不这样做,将不可避免地导致内存问题和异常。或者,您可以使用类似char的vector。

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:

Item(char* item, int itemType) {
    strncpy(_item, item, 200);
}