0

When I override copy constructor why it segfaults in first delete itself. output:

$./a.out
inside ctor
inside copy-ctor
Say i am in someFunc
inside dtor
*** glibc detected *** ./a.out: free(): invalid pointer: 0xb75f3000 ***

if I do not override copy-ctor then I could see that s1.PrintVal() is getting called and then there is seg fault in *ptr that is expected.

Why there is two different behavior with and without default and overridden copy-ctor?

#include<iostream>
using namespace std;
class Sample
{
public:
    int *ptr;
    Sample(int i)
    {
        cout << "inside ctor" << endl;
        ptr = new int(i);
    }
    Sample(const Sample &rhs)
    {
        cout << "inside copy-ctor" << endl;
    }
    ~Sample()
    {
        cout << "inside dtor" << endl;
        delete ptr;
    }
    void PrintVal()
    {
        cout <<" inside PrintVal()."<<endl;
        cout << "The value is " << *ptr<<endl;
    }
};
void SomeFunc(Sample x)
{
    cout << "Say i am in someFunc " << endl;
}

int main()
{
    Sample s1= 10;
    SomeFunc(s1);
    s1.PrintVal();
    return 0;
}
mwerschy
  • 1,698
  • 1
  • 15
  • 26
user1174114
  • 178
  • 1
  • 19
  • 2
    Once you've fixed this, remember the [Rule of Three](http://stackoverflow.com/questions/4172722) and give it a copy-assignment operator as well. – Mike Seymour May 10 '13 at 15:42

2 Answers2

3

In your copy-ctor, you don't actually copy ptr, meaning its value will be unspecified, and you'll be deleting an unspecified pointer (instead of double-deleting a normal pointer as you do with the defauly copy-ctor).

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

The default copy ctor copies every member by value. This will create an alias to the pointer so each class when its dtor is called will delete the pointer and cause a fault.

In almost any class where you have a pointer that is being allocate you will need to write a custom copy constructor to allocate the pointer and then copy the value.

class Sample
    {
            public:
                            int *ptr;
                            Sample(int i)
                            {
                                    cout << "inside ctor" << endl;
                                    ptr = new int(i);
                            }
                            Sample(const Sample &rhs)
                            {
                                    ptr = new int(*rhs.ptr);
                            }
                            Sample & operator=(const Sample& other)
                            {
                                // You should also override copy assignment if you overide copy 
                                // you don't need to allocate in this case just copy the value 
                                *ptr = *other.ptr;
                            }
                            ~Sample()
                            {
                                    cout << "inside dtor" << endl;
                                    delete ptr;
                            }
                            void PrintVal()
                            {
                                    cout <<" inside PrintVal()."<<endl;
                                    cout << "The value is " << *ptr<<endl;
                            }
    };

You should look up the rule of three and if your in c++ 11 the rule of five

rerun
  • 25,014
  • 6
  • 48
  • 78