In the following code, why does s1.printVal
causes a dangling pointer error? Isn't the s1
object, i.e. its pointer, still accessible until it's destroyed?
class Sample
{
public:
int *ptr;
Sample(int i)
{
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value is " << *ptr;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1 = 10;
SomeFunc(s1);
s1.PrintVal(); // dangling pointer
}
The problem here is the copy that is done for argument of the SomeFunc()
. That copy de-allocates your pointer when destroyed. You need to also implement a copy constructor, and copy assignment operator. See rule of three.
Here's "expanded" pseudo-code, i.e. what the compiler does for you in the main()
function:
// main
addr0 = grab_stack_space( sizeof( Sample )); // alloc stack space for s1
Sample::ctor( addr0, 10 ); // call ctor of Sample
addr1 = grab_stack_space( sizeof( Sample )); // alloc stack for argument
Sample::ctor( addr1, addr0 ); // call COPY-ctor of Sample
SomeFunc( addr1 ); // call SomeFunc
Sample::dtor( addr1 ); // XXX: destruct the copy
free_stack_space( addr1, sizeof( Sample )); // free stack taken by copy
Sample::PrintVal( addr0 ); // call member func on s1
Sample::dtor( addr0 ); // destruct s1
free_stack_space( addr0, sizeof( Sample )); // YYY: free stack taken by s1
This is not the exact representation, but a conceptual explanation. It just helps to think in terms of what compiler has to do with your code.
The pointer member of Sample
is delete
-ed at the step marked with XXX
, and then delete
-ed again at the step YYY
.