Reputation: 1406
I have read that if we have pointers inside our class then we need to implement our own copy constructor; otherwise, two classes will have pointers pointing to the same memory location, and calling delete on one of them makes the other null as well. I am trying to simulate the above condition by writing a code like this:
class A
{
private:
int *p;
public:
A()
{
p = new int(10);
}
~A()
{
delete p;
cout << "Calling destructor" << endl;
}
};
int main(int argc, char **argv)
{
A a;
A aa = a;
}
I am expecting some exception to be thrown as I have not explicitly declared my copy constructor and I am using pointers as well. But program runs perfectly. Can anybody please suggest a modification so that I am able to understand under what condition exception will occur?
Upvotes: 0
Views: 234
Reputation: 57749
Your issue is the same as having two pointers pointing to one instance and the instance is deleted.
Given the following code:
int main(void)
{
int * pointer_1 = NULL;
int * pointer_2 = NULL;
pointer_1 = new int;
*pointer_1 = 42;
// Make both pointers point to the same dynamically allocated object.
pointer_2 = pointer_1;
// Let's delete the instance
delete pointer_1;
// The delete operator does not change the value of pointer_1.
// Pointer_1 still points to *something*, but that *something* has been deleted.
return 0;
}
In the above example, delete
does not affect the value of pointer_1
or pointer_2
. Only the object isn't there anymore. Nothing in the C or C++ standard says that the program must be notified when the memory is deleted or the pointers changed.
There is nothing stating that when memory is deleted, the implementation must change every pointer that was pointing to the memory deleted.
Because the object isn't there anymore, deferencing the pointers will generate undefined behavior. The contents may have a shadow in memory, or the operating system may have removed the page completely from memory (a.k.a. memory paging).
The OS may throw an exception but the C and C++ languages do not force compiler libraries to generate exceptions. After all, in some embedded systems, address 0 is a valid memory location.
Try printing the value of the pointers at each step to verify.
I tell you and your friend to point to a rug on the floor. I remove the rug. What are you and your friend pointing to?
Upvotes: 1
Reputation: 333
I don't think this will ever throw an "exception" per say. You may get undesirable side effects like SEGV or worse memory corruption. To understand why you need the copy constructor you can think of how the objects 'a' and 'aa' will look.
Assume, new int(10) returns a pointer value 0xfeedface, where *(int *)(0xfeedface) == 10. Your objects will look like,
a -> { p=0xfeedface} aa -> { p=0xfeedface}
Now if you destruct object-a the memory '0xfeedfac'e will get unallocated & go back to your allocators freelist. Consider what happens to object-aa. It is still holding a reference to 0xfeedface, but that memory that has already been freed! Now if object-aa tries to dereference *p it can get potentially random value (depending on what the allocator does or if the object has been allocated to some other object). Also, terrible things can happen if object-aa ever tries to write to p=0xfeedface.
If you want to mandate writing a copy constructor, one way i can think of is to create a base class & assert if it ever gets called.
#include <iostream>
#include <cassert>
class base
{
public:
virtual void operator=(const base& )
{
assert(! "No copy constructor for class derived from base");
}
};
class derived : public base
{};
int
main()
{
derived d, d1;
d1 = d;
}
The above code will assert since class derived hasn't provided with a copy constructor. It would be ideal to have this be caught at compile time instead. But I can't think of a way of doing that right now.
[caveat: the above solution won't work well for multiple levels of inheritance]
Upvotes: 0
Reputation: 6230
Something like this
A * a = new A();
A * b = a;
delete a;
stdout << (*(b->p));
But delete
should only make the memory free for other parts of your program to use, not necessarily null
it.
Upvotes: 0
Reputation: 154047
Your code does delete
the same pointer twice. This is
undefined behavior, and one of the possible symptoms of
undefined behavior is that it can seem to work. (In my
experience, the most frequent symptom is that everything works
perfectly until you present it to the public, at which time, it
starts crashing right and left.)
Upvotes: 5