2

I'm trying to delete the dynamic memory in the destructor of user defined exception which is allocated in the constructor of user defined exception. But I get core dump stating that the memory is freed twice:

user1@ubuntu:~/practice$ ./a.out
Test Exception
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000000f0b0b0 ***
Aborted (core dumped)

I suspect the MyException object is going out of scope two times, one in myfunc() and another in main's catch block which is causing this issue. But I could not figure out how to free the memory in this case. Can you help me?

Here's the code:

#include<iostream>
#include<exception>
#include<cstring>
using namespace std;

class MyException: public exception
{
    char *msg;
    public:
    MyException(){}
    MyException(char *str)
    {
        msg = new char[strlen(str)+1];
        strcpy(msg,str);
    }
    char *what()
    {
        return msg;
    }
    ~MyException() throw()
    {
        delete msg;
    }
};

class A
{
    public:
    void myfunc() throw(MyException)
    {
        throw MyException((char*)"Test Exception");
    }
};

int main()
{
    try
    {
        A ob;
        ob.myfunc();
    }
    catch (MyException e)
    {
        cout<<e.what()<<endl;
    }
}
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
Elangovan Manickam
  • 413
  • 1
  • 5
  • 14
  • 1
    You need `reference count` for it. BTW: You should use `delete[]` instead of `delete`. – songyuanyao Feb 12 '15 at 07:06
  • I think you also need to obey the Rule of Three – M.M Feb 12 '15 at 07:09
  • 2
    Check out [The Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29). – R Sahu Feb 12 '15 at 07:09
  • A good practice is to catch exception by `const reference`, then the exception is not copied. So if you write like this: `catch (const MyException& e)`, it's OK. But of source you still need to obey the Rule of Three. – Mine Feb 12 '15 at 07:20
  • Well done, a question that contains all the relevant information! – moooeeeep Feb 12 '15 at 07:29
  • 1
    Also note that the signature if `std::exception::what` is `const char* what() const;`. You aren't overriding it. – juanchopanza Feb 12 '15 at 07:39
  • 1
    And finally, you can change the constructor to `MyException(const char *str)`, so that you don't have to do a nasty const cast on string literals. – juanchopanza Feb 12 '15 at 07:40

1 Answers1

2

The problem is resolved by following The Rule of Three. What is The Rule of Three?

From another SO answer:

If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.

More details can be found at another SO question and Wikipedia.

#include <iostream>
#include <exception>
#include <cstring>

using namespace std;

class MyException: public exception
{
    char *msg;
    public:
    MyException(const char *str)  // Making the constructor take a `const char*`
                                  // so it can be invoked with a string
                                  // literal
    {
        msg = new char[strlen(str)+1];
        strcpy(msg,str);
    }
    MyException(MyException const& copy)
    {
        msg = new char[strlen(copy.msg)+1];
        strcpy(msg,copy.msg);
    }
    char const* what() const // Making the return type 'const char*' and
                             // making the member function a const. That's
                             // necessary to make it an override of
                             // std::exception::what()
    {
        return msg;
    }
    ~MyException() throw()
    {
        delete msg;
    }
    MyException& operator=(MyException const& rhs)
    {
       if ( this != &rhs )
       {
          delete [] msg;
          msg = new char[strlen(rhs.msg)+1];
          strcpy(msg,rhs.msg);
       }
       return *this;
    }
};

class A
{
    public:
    void myfunc() throw(MyException)
    {
        throw MyException((char*)"Test Exception");
    }
};

int main()
{
    try
    {
        A ob;
        ob.myfunc();
    }
    catch (MyException e)
    {
        cout<<e.what()<<endl;
    }
}

Output:

Test Exception
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270