【问题标题】:char array corruption in C++C ++中的char数组损坏
【发布时间】:2011-10-10 01:28:21
【问题描述】:

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

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;
}

不用担心 _tweetID,这是我程序的另一个功能部分,与我的问题无关。

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

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() 之间,char 数组丢失或类似的东西。

知道出了什么问题吗?如果你需要,我会给你更多代码。

【问题讨论】:

  • 你可能想在类声明中写memcpy(_item, item, 200);并将_item声明为char _item[200],这样它的寿命就会比构造函数的实例长。
  • @ruslik 我将临时数组放入我的类字段中,现在效果很好。感谢您的帮助!
  • 请阅读What are the rules about using an underscore in a C++ identifier?。它会在以后为您节省一些惊喜。

标签: c++ arrays printing char cout


【解决方案1】:

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

_item = item;

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

下次你去阅读这个位置时,它可能是有效的——不过,它很可能是垃圾,正如你所看到的那样。

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

编辑,解决您的评论:

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

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

【讨论】:

  • strcpy 每次使用都会让我的程序崩溃。我也尝试手动复制 char 数组,但没有帮助。'
  • 您需要在strcpy() 进入内存之前分配内存。为什么不使用标准库中的string 和list 类?
  • 我只能使用iostream和cstring。
  • @Johnsyweb - c++ 有标准库吗?我以为只是 c 类;^)
  • @SkylineAddict:如果你有这样的限制,你应该在你的问题中说明它(以及它的原因)。
【解决方案2】:

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

最后,所有引用此内存位置的对象都将无效。

还有.... 如果要传递对数组的引用,请这样做:

Item(char** item, int itemType)

【讨论】:

  • 寿命是主要问题。将我的临时数组放在类的字段中,而不是在修复它的函数中声明它。谢谢!
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

    在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);
    }
    

    【讨论】:

    • 我的做法几乎正是我的教授希望我做的。唯一的区别是,他希望我使用 strcpy 进行复制,而不是手动进行。我发现 strcpy 对我来说比帮助更麻烦,所以我最终没有使用它。
    猜你喜欢
    • 2020-01-22
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多