C++ error: double free or corruption (fasttop)

匿名 (未验证) 提交于 2019-12-03 01:39:01

问题:

I'd like to know why the following program gets the error "double free or corruption (fasttop)" when I run the program. I know I can use string instead of character array. But I'd like to use character array with dynamic memory allocation. Could you please let me know how I can fix this problem?

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

回答1:

You forgot to define operator= for your class. This is the rule of Big Three (copy ctor, dtor, assignment must all be defined).



回答2:

n.m. has already given a fine answer, but I found this question interesting so I decided to try to understand it a little better.

It turns out then when you call erase() on the first item of an iterator (which we will call item0), here's what the iterator does: it uses the = operator of your class to do item0 = item1. Then it deletes item1.

If you don't define your own = operator, I think it will simply copy the memory of your object over from item1 to item0, so item0 and item1 will temporarily be pointing to the same string. Then when item1 gets deleted, the string gets freed, leaving item0 in an invalid state because it has a pointer to memory that has been freed.

Here is some simple test code that reproduces and illuminates the problem:

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

This code produces the following output:

== 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 

I compiled and ran this in Windows with MinGW. The command I used was g++ -Wl,--enable-auto-import test.cpp && a.exe.



回答3:

If it hurts, don't do it:

#include <iostream> #include <string> #include <vector> using namespace std;  class Cube { public:     string str;      Cube(const string& s) : str(s) { } };  int main() {     vector <Cube> vec;      for (int i = 0; i < 10; i++)     {         char in [] = "hello !!";         vec.push_back(Cube(in));     }       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;     } 

Happens to be shorter and correct (not tested).



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!