我想知道为什么以下程序在运行程序时会出现"双重自由或损坏(fasttop)"错误.我知道我可以使用字符串而不是字符数组.但是我想使用带有动态内存分配的字符数组.能告诉我如何解决这个问题吗?
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
class Cube
{
public:
char *str;
Cube(int len)
{
str = new char[len+1];
}
Cube(const Cube &c)
{
str = new char[strlen(c.str) + 1];
strcpy(str, c.str);
}
~Cube()
{
delete [] str;
}
};
int main()
{
vector <Cube> vec;
for (int i = 0; i < 10; i++)
{
char in [] = "hello !!";
Cube c(strlen(in)+1);
strcpy(c.str, in);
vec.push_back(c);
}
int i = 0;
for ( vector<Cube>::iterator it = vec.begin(); it < vec.end(); )
{
cout << it->str << endl;
i++;
if (i % 2 == 0)
it = vec.erase(it);
else
it++;
}
for ( vector<Cube>::iterator it = vec.begin(); it < vec.end(); it++)
{
cout << it->str << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
nm已经给出了一个很好的答案,但我发现这个问题很有趣,所以我决定尝试更好地理解它.
事实证明,当你调用erase()迭代器的第一项(我们将调用它item0)时,这就是迭代器的作用:它使用=你的类的运算符来做item0 = item1.然后删除item1.
如果你没有定义自己的=运算符,我认为它只是简单地将对象的内存复制item1到item0,所以item0并item1暂时指向同一个字符串.然后当item1被删除时,字符串被释放,item0处于无效状态,因为它有一个指向已释放的内存的指针.
这是一些简单的测试代码,可以重现并解决问题:
#include <cstring>
#include <vector>
#include <stdio.h>
using namespace std;
class Cube
{
public:
char * str;
Cube(const Cube &c) { set(c.str); }
Cube(const char * s) { set(s); }
~Cube() { clear(); } // is "delete []" necessary? not sure
#if 1 // change to 0 to cause a bug
void operator=(const Cube &c)
{
clear(); // necessary to avoid memory leaks
printf("operator=\n");
set(c.str);
}
#endif
private:
void set(const char * s)
{
str = new char[strlen(s) + 1];
printf("allocated %p for %s\n", str, s);
strcpy(str, s);
}
void clear()
{
if (str)
{
printf("freeing %p: %s\n", str, str);
delete str;
}
}
};
int main(int argc, char ** argv)
{
printf("== CREATING VECTOR ==\n");
vector <Cube> vec;
vec.push_back(Cube("octopus"));
vec.push_back(Cube("squid"));
printf("== BEGINNING ITERATION ==\n");
vector<Cube>::iterator it = vec.begin();
printf("First entry is %p %s\n", it->str, it->str);
it = vec.erase(it);
printf("Second entry is %p %s\n", it->str, it->str); // this prints garbage if Cube has no = operator
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码生成以下输出:
== CREATING VECTOR ==
allocated 00350F98 for octopus
allocated 00350FB8 for octopus
freeing 00350F98: octopus
allocated 00350F98 for squid
allocated 00350FD8 for squid
allocated 00350FE8 for octopus
freeing 00350FB8: octopus
freeing 00350F98: squid
== BEGINNING ITERATION ==
First entry is 00350FE8 octopus
freeing 00350FE8: octopus
operator=
allocated 00350F98 for squid
freeing 00350FD8: squid
Second entry is 00350F98 squid
freeing 00350F98: squid
Run Code Online (Sandbox Code Playgroud)
我使用MinGW在Windows中编译并运行它.我用的命令是g++ -Wl,--enable-auto-import test.cpp && a.exe.