[ACCEPTED]-C++ error: double free or corruption (fasttop)-vector

Accepted answer
Score: 13

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

Score: 6

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

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

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

Here is some simple 4 test code that reproduces and illuminates 3 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 2 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 1 with MinGW. The command I used was g++ -Wl,--enable-auto-import test.cpp && a.exe.

Score: 0

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 1 and correct (not tested).

More Related questions