different behavior of destructor

S

sacgarg

Following code is behaving strange:


class WithPointerMember
{
char* str;
const size_t size;
public:
WithPointerMember():size(15) //ctor
{
str = new char[size];
strcpy(str, "Initialized");
}

WithPointerMember (const WithPointerMember& other):size(other.size)
//copy ctor
{
str = new char[size];
for(size_t i=0;i<size;i++)
str= other.str;
}

char* GetString(void) const
{
return str;
}

~WithPointerMember() //dtor
{
delete [] str;
}
};

Now In main function first I do like
int main(void)
{
WithPointerMember wpm;
WithPointerMember wpm1 = wpm; <---------- Initializing wpm1 from wpm
cout<<"string="<<wpm.GetString()<<"\n";
wpm.~WithPointerMember();
cout<<"string="<<wpm.GetString()<<endl;
cout<<"string="<<wpm1.GetString()<<endl;
return 0;
}

The output is expected :

string=Initialized
string=
string=Initialized

Now I change my main:
int main(void)
{
WithPointerMember wpm;
cout<<"string="<<wpm.GetString()<<"\n";
wpm.~WithPointerMember();
WithPointerMember *wpm1 = new WithPointerMember(); <-------
Initializing wpm1 from new
cout<<"string="<<wpm.GetString()<<endl;
cout<<"string="<<wpm1->GetString()<<endl;
return 0;
}

Here Output is : ( which is not expected )
string=Initialized
string=Initialized <------ This is not expected
string=Initialized

Can anybody explain that what is going wrong here. I am running code on
Windows using MSVC compiler

Thanks.
sacgarg
 
F

ferdinand.stefanus

Now I change my main:
int main(void)
{
WithPointerMember wpm;
cout<<"string="<<wpm.GetString()<<"\n";
wpm.~WithPointerMember();
WithPointerMember *wpm1 = new WithPointerMember(); <-------
Initializing wpm1 from new
cout<<"string="<<wpm.GetString()<<endl;
cout<<"string="<<wpm1->GetString()<<endl;
return 0;
}

Here Output is : ( which is not expected )
string=Initialized
string=Initialized <------ This is not expected

It's expected, actually. You called the destructor before, which
deletes WithPointerMember::str. Anything you do afterwards that involve
the str member can produce anything. Do you really need to call the
destructor explicitly? And have you considered using std::string?
 
B

Ben Pope

sacgarg said:
Following code is behaving strange:


class WithPointerMember
{
char* str;
const size_t size;
public:
WithPointerMember():size(15) //ctor
{
str = new char[size];
strcpy(str, "Initialized");
}

WithPointerMember (const WithPointerMember& other):size(other.size)
//copy ctor
{
str = new char[size];
for(size_t i=0;i<size;i++)
str= other.str;
}

char* GetString(void) const
{
return str;
}

~WithPointerMember() //dtor
{
delete [] str;
}
};

Now In main function first I do like
int main(void)
{
WithPointerMember wpm;
WithPointerMember wpm1 = wpm; <---------- Initializing wpm1 from wpm


Beware, you have not created an operator=, although you are not using it
here. Prefer:

WithPointerMember wpm1(wpm);
cout<<"string="<<wpm.GetString()<<"\n";
expect:
string=Initialized

wpm.~WithPointerMember();

OK, this deallocated the internal string.
cout<<"string="<<wpm.GetString()<<endl;

Undefined behaviour. You cannot call member functions on destructed
objects. The rest of the program is useless.
cout<<"string="<<wpm1.GetString()<<endl;
return 0;

What do you expect to happen now? wgm and wgm1 will be destructed, you
cannot call the destructor of an object twice, it invokes undefined
behaviour.
}

The output is expected :

string=Initialized

Up to here is fine.
string=
string=Initialized

You cannot reasonably expect anything after invoking undefined behaviour.
Now I change my main:
int main(void)
{
WithPointerMember wpm;
cout<<"string="<<wpm.GetString()<<"\n";
Expect:
string=Initialized

wpm.~WithPointerMember();
WithPointerMember *wpm1 = new WithPointerMember(); <-------
Initializing wpm1 from new
cout<<"string="<<wpm.GetString()<<endl;

wpm has been destructed, more undefined behaviour...
cout<<"string="<<wpm1->GetString()<<endl;
return 0;
}

Here Output is : ( which is not expected )
string=Initialized
string=Initialized <------ This is not expected
string=Initialized

Can anybody explain that what is going wrong here. I am running code on
Windows using MSVC compiler

Stop calling the destructor explicitly. Trust me, you'll never need to.
What are you trying to achieve?

Ben Pope
 
S

sacgarg

It's expected, actually. You called the destructor before, which
deletes WithPointerMember::str. Anything you do afterwards that involve
the str member can produce anything. Do you really need to call the
destructor explicitly? And have you considered using std::string?

calling destructor explicitly is intentional, just to test the
behaviour.

I have already read in 'Undefined behaviour in C' that once you free
the memory, referencing it again can give you anything.

Is it same here?
 
S

sacgarg

Ben said:
sacgarg said:
Following code is behaving strange:


class WithPointerMember
{
char* str;
const size_t size;
public:
WithPointerMember():size(15) //ctor
{
str = new char[size];
strcpy(str, "Initialized");
}

WithPointerMember (const WithPointerMember& other):size(other.size)
//copy ctor
{
str = new char[size];
for(size_t i=0;i<size;i++)
str= other.str;
}

char* GetString(void) const
{
return str;
}

~WithPointerMember() //dtor
{
delete [] str;
}
};

Now In main function first I do like
int main(void)
{
WithPointerMember wpm;
WithPointerMember wpm1 = wpm; <---------- Initializing wpm1 from wpm


Beware, you have not created an operator=, although you are not using it
here. Prefer:

Thanks for mentioning that, but I was aware that I am not going to use
it.
WithPointerMember wpm1(wpm);


OK, this deallocated the internal string.


Undefined behaviour. You cannot call member functions on destructed
objects. The rest of the program is useless.
Here by calling destructor explicitely, I am not destructing object
itself, instead I am deleting the internal string, then how come object
is destructed? I am confused.
What do you expect to happen now? wgm and wgm1 will be destructed, you
cannot call the destructor of an object twice, it invokes undefined
behaviour.


Up to here is fine.


You cannot reasonably expect anything after invoking undefined behaviour.


wpm has been destructed, more undefined behaviour...


Stop calling the destructor explicitly. Trust me, you'll never need to.
What are you trying to achieve?
This is intentional for testing the behaviour of pointer member.
 
B

Ben Pope

sacgarg said:
Thanks for mentioning that, but I was aware that I am not going to use
it.

In real code, you should declare it private and not implement it.
Attempts to use it will be caught by the compiler.
Here by calling destructor explicitely, I am not destructing object
itself, instead I am deleting the internal string, then how come object
is destructed? I am confused.

You are destructing the object, the compiler may be doing some other
background stuff that you are not aware of. It is as free to do this,
as it is to implement it's own constructor, destructor, copy constructor
and assignment operator if you do not provide one.

In that destructor you deallocate the internal buffer. One of the
invariants of your object is that the internal buffer exists. Take a
look at the member functions, they all assume that str points to a valid
char[] (GetString may be able to get away with a NULL str). Therefore,
having str point to a valid char[], or NULL is an invariant.
This is intentional for testing the behaviour of pointer member.

Well, after invoking undefined behaviour, your tests are meaningless.

Ben Pope
 
R

Rolf Magnus

sacgarg said:
Here by calling destructor explicitely, I am not destructing object
itself,

Yes you are. Guess why it is called "destructor".
instead I am deleting the internal string, then how come object is
destructed? I am confused.

When an object is created, two things happen:

- raw memory is acquired
- a constructor is used to turn that raw memory into an object

After the destructor was executed, you can't expect an object anymore. It is
now back to raw memory.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top