根据我的阅读,我不应该对我的代码有问题。 我正在阅读Alex Allain跳转到C ++,他像这样复制动态int数组,但是当我尝试以同样的方式复制struct数组时,它给了我这个错误:
Unhandled exception at 0x777108B2 in Friend Tracker.exe: Microsoft C++ exception: std::length_error at memory location 0x006FF838.
根据我的理解,这告诉我用完了堆数据。但是我有14GB未使用的RAM,这怎么可能?
在查看具有相同错误的其他人的问题时,他们正在保存1GB大小的数组副本。
这让我觉得它在我的内存中的位置是问题,但为什么编译器没有在我的新数组中分配正确数量的堆数据?
struct frnd
{
string firstName;
string lastName;
int lastTalked;
};
int main()
{
int size = 1;
frnd* friendsList;
friendsList = new frnd[2];
friendsList[1].firstName = "larry";
frnd* temp;
temp = new frnd[4];
for (int i = 1; i < 3; i++)
{
temp[i] = friendsList[i];
}
delete[] friendsList;
friendsList = new frnd[4];
for (int i = 1; i < size; i++)
{
friendsList[i] = temp[i];
}
delete[] temp;
cout << "\n\n" << friendsList[1].firstName << "\n\n";
system("PAUSE");
return 0;
}
答案 0 :(得分:3)
您的错误是由于C ++中的数组索引从零开始,但您正在使用它,就像数组是基于一样的。
for (int i = 1; i < 3; i++) {
temp[i] = friendsList[i];
}
friendsList
指向双元素数组中的第一个元素。这访问friendsList[1]
,这没关系。 (但请注意,它是数组中的第二个元素,而不是第一个元素。)
在下一次迭代中,它访问friendsList[2]
,它将是数组的第三个元素,但是您的数组只有两个元素。因此,这是一个超出范围的数组访问,它会导致未定义的行为。在您的情况下,这表现为以下事件序列的例外:
friendsList[2]
对象(frnd
),但这超出了数组分配的范围。 这是未定义的行为,不好,完全停止。但是,为了解释为什么,你得到这个特定的例外...... frnd
对象使用默认的复制构造函数,它只是将源对象的每个数据成员复制到目标。friendsList[2].firstName
时,你有效地使用与你的分配相邻的其他内存作为std::string
对象,当没有构造这样的对象时那个记忆区域。std::string
复制赋值运算符尝试读取字符串内部数据成员并获取垃圾(未初始化和/或不确定值,这里的区别毫无意义,因为我们已经很好地进入了UB区域)。它可能尝试做的第一件事是使用来自不存在的源字符串对象的垃圾“字符串长度”值分配char
数组,如果 成功,那么它将尝试从未初始化指针指向的内存区域复制许多字符。远离这种“复制我的垃圾数据就好像它是一个string
对象”操作而没有某种异常的可能性非常非常低。
&friendsList[2]
可能指向尚未映射到进程的地址空间的内存区域,在您尝试从中读取时会触发访问冲突。 这实际上比调用UB时可能发生的其他事情更可取。 您可以通过调整循环的界限来解决此问题:(int i = 0; i < 2; i++)
另一方面,你的第二个循环什么都不做,因为i
和size
都是1,所以测试i < size
失败。
正如您对问题的评论中所指出的,在尝试复制对象之前,您也不会初始化对象的lastTalked
成员。除了一些例外,reading an uninitialized value causes undefined behavior。因此,从技术上讲,即使i
为1时的第一次循环迭代也会调用未定义的行为,但是使用特定的编译器和体系结构,这可能表现为不确定值的副本。
这可以通过添加初始化成员的默认frnd
构造函数来修复:
struct frnd
{
frnd() : lastTalked(0) { }
string firstName;
string lastName;
int lastTalked;
};
关于您的代码的其他想法:
std::vector
。using namespace std;
是bad practice。