2

Would anyone please explain this case: why I am facing 'double free' problem in this simple code?

void Rreceive (myclass){}

int main () {
    myclass msg (1);
    Rreceive(msg);
    return 0;
}

where myclass is:

class myclass
{
    private:
        HeaderType header;
        byte * text;    

    public:
        myclass(int ID);
        ~myclass();
        HeaderType getHeader();
        byte * getText();
};

myclass::myclass(int ID){
    header.mID = ID;
    text = (byte *)malloc (10);
    memset (text, '.', 10);
}

myclass::~myclass(){
    free (text);
}

HeaderType myclass::getHeader(){
    return header;
}

byte * myclass::getText(){
    return text;
}

and HeaderType is:

typedef struct {
    int mID;
}HeaderType;

The error is: *** glibc detected *** ./test: double free or corruption (fasttop): 0x0868f008 ***...

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • 5
    Rule of three: if you need any one of a user-defined copy constructor, copy assignment operator, or destructor, you most likely need all three. You pass `myclass` around by value, which means copies are being created and then destroyed. An implicit copy constructor simply copies `text` pointer, so you have multiple instances holding the same pointer, which then they all try to `free`. – Igor Tandetnik Jan 29 '15 at 15:51
  • @IgorTandetnik indeed, I have them in my main code (more than 1000 lines) where I faced the problem. I reduced my code to these lines and I still face the same error. – محمد جعفر نعمة Jan 29 '15 at 15:53
  • Well, I explained why you have double-destruction in the code you've shown. You can hardly expect me to be able to comment on the code you haven't shown. – Igor Tandetnik Jan 29 '15 at 15:54
  • 1
    your function gets a copy of your class with the same pointer, and when its scope ends, the copy is destroyed, freeing it. When main returns, the original is destroyed, freeing it again. – Not a real meerkat Jan 29 '15 at 15:55
  • http://www.aristeia.com/ddjpaper1.html – Hans Passant Jan 29 '15 at 15:55
  • @IgorTandetnik this should be an answer. Maybe would be good to consider that rule of three becomes rule of five on c++11 – Slava Jan 29 '15 at 15:55
  • 1
    Explained here: [What is The Rule of Three?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – anatolyg Jan 29 '15 at 15:57
  • 1
    @Moi I removed comments from your code; I hope it's clearer now. Feel free to revert if you disagree. – anatolyg Jan 29 '15 at 16:06
  • One solution is to implement copy constructor and copy assignment with deep copy. But I prefer to forbid copy constructor and copy assignment and only allow pass by reference and pass by pointer. It depends on your choice of pass by value or pass by reference or pointer, but if latter two serves your purposes, then you save yourself the trouble of implementing copy constructor and copy assignment yourself. – user3528438 Jan 29 '15 at 16:18

1 Answers1

5

When you enter your Rreceive function you call the default copy constrcuctor which will not make a deep copy of your text pointer (in other words, he will just assign the pointer to the new copy).

When exiting the Rreceive scope you free (text) from the copied instance, which will point to the same memory address.

The you will try to free the same memory address again when exiting the scope of your main function.

MichaelCMS
  • 4,703
  • 2
  • 23
  • 29