Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Can someone help me understand on what is happening in the C++code

Posted on 2014-04-09
12
Medium Priority
?
179 Views
Last Modified: 2014-05-26
Following is a simple class A1 and it is being used in Main.cpp file.

CLASS: A1
#include <iostream>
#include <string.h>

using namespace std;

class A1 {
public:
	char* p;
	A1(const char* str){
		p = new char(strlen(str)+1);
		strcpy(p,str);
	}

	virtual ~A1(){
		delete p;
	}
};

Open in new window

---------------------------------------------
Main.cpp

#include "A1.h"
int main(){
 A1 s("go Gama");
 s.~A1();
 printf(s.p);
 printf("one\n");
 A1 u("go Beta\n");
  //u=s;
 printf(s.p);
 printf("two\n");
}

Open in new window

---------------------------------------------
Expected output: one , two
BUT i get :one , go Beta , two

How can s.p still have a value which I have added to another instance u?
0
Comment
Question by:pvinodp
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
  • +1
12 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39988507
Why are you still trying to access "s" after you called its destructor in line 4? You should not be attempting to access deleted data/pointers after the fact. Line 9 would be OK if line 8 were uncommented, but lines 4 & 5 are always wrong to do (if done in that order).
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 39988561
I must admit that I've learned something today... because I didn't even realize that you could call a class destruct-or directly.  

Typically, the destructor gets called automatically when a local class object goes out of scope, or you create the class object with 'new' and call the destructor via 'delete'.

The only thing I see that even allows this code to run as far as it does is the fact that calling ~A1() doesn't destroy the s object, it simply executes the code that is in the ~A1() function.  If the class had been inherited, I'm not even sure that calling the ~A1() destructor function directly would properly call the base class destructors.

So bottom line, I think calling ~A1() directly is the wrong thing to ever do because you're interfering the with life-cycle of the object.  By calling ~A1, you're not destroying the object, but you are executing some of the code normally associated with destroying the object.  So I would compare it to an attempted suicide gone wrong.
0
 

Author Comment

by:pvinodp
ID: 39988619
even if line 4 is wrong.
how can line number 7->  A1 u("go Beta\n"); put data into s?
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
ID: 39989061
Don't quote me, but perhaps the application is writing straight back to that location in memory since you have told it that you would like to delete it (via line 15), and that memory is now free (for the operating system) to use. It's the same size as what you requested before. (Remember:  A pointer just holds an address to some other location in memory. The fact that it points to a string is inconsequential; the data actually being held by the pointer itself is a memory address.) If you ran this code over many repetitions, then you might see different behavior.
0
 
LVL 16

Assisted Solution

by:HooKooDooKu
HooKooDooKu earned 1500 total points
ID: 39989309
I missed the fact that you are loading 'u' with "go Beta" and printing 's' and getting "go Beta".

That would mean that what kaufmed (combined with what I said) is why you are getting the 'wrong' text.

You created 's' and assigned it to point to a 'new' string.  You then called the 's' destructor.  But you didn't really destroy 's', all you did was run the member function '~A1()'.  That member function released the memory that s.p was pointing to.  But it didn't change the memory location s.p was pointing to.

Then you created 'u' where a new string was created and u.p now points to.  But if you look at the code with a debugger, you should find that u.p happens to be the exact same memory address that s.p was left pointing to.

Since 's' was never actually destroyed, it is still a valid object and s.p points to the string that 'u' created.  You don't get a memory exception because the local function has access to the memory that u.p points to, but you're just reading the memory address using s.p.

If you change the ~A1() destructor to the following, your program with blow chunks with a memory exception.
virtual ~A1()
{
delete p;
p = NULL;
}

Open in new window

0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39989456
your program with blow chunks...
Is that a technical term?

XD
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 39990047
Is that a technical term?
Close enough...

Most programs will irrecoverably crash if it encounters a memory access violation (and most systems don't allow access to memory location 'NULL').  Even if you put try/catch blocks around the code that causes a memory access violation, the program will crash instead of throwing a catch-able exception (at least that's been my experience with Visual Studio... a special compiler option has to be set so that access violations will throw catch-able exceptions.)
0
 

Author Comment

by:pvinodp
ID: 39990903
No crash happened. I even removed teh line 15 from definition of A and let p=NULL stay.

I accept that same memory is being allocated and that is the reason. But why and how can this happen that the address is valid after I deleted p
0
 
LVL 16

Assisted Solution

by:HooKooDooKu
HooKooDooKu earned 1500 total points
ID: 39991480
I even removed teh line 15 from definition of A and let p=NULL stay.
Unless you've modified the code from what you first posted, 'p' is never NULL.

As the A1 object ('s' or 'u') is created, the pointer p is just random data left in memory until the line 'p = new ...' is executed.

When you delete 'p' on line 15, the value of 'p' doesn't change.  The 'delete' just frees the memory that 'p' pointed to.  But unless you change the value of 'p', the 'delete' command just leaves 'p' pointing to freed memory.

Now if you modify the code so that after 'delete p' you assign 'p = NULL', THEN line 9 in Main.cpp will crash because it will attempt to access NULL as it attempts to access the memory that 'p' is pointing to.
0
 
LVL 35

Expert Comment

by:sarabande
ID: 39992347
just to add to above comments:

i often saw code in the destructor where pointers deleted were set to NULL like in the sample code HooKooDooKu has shown.

i thought it was just for readability or to please some purifier software.  but, same as with HooKooDooKu, I never have seen code before which calls the destructor as a function.

But why and how can this happen that the address is valid after I deleted p
a pointer value is an address in the memory. the address is still valid if you free the pointer by delete as told by HooKooDooKu. the heap manager could check if it is valid as it "knows" whether a pointer was allocated or not, but the compiler has not added such a check when you access a pointer read-only after freeing. you even could write to that memory beside a debugger would do a check before write (i know debuggers which would write funny addresses like 0xefefefef to deleted pointers, which then really is invalid). if you definitively want to see a crash you would need to delete the pointer again. in any case, if your application grows, such code would lead to severe memory corruption and unpredictable crashes.

Sara
0
 
LVL 16

Accepted Solution

by:
HooKooDooKu earned 1500 total points
ID: 39992984
No crash happened. I even removed teh line 15 from definition of A and let p=NULL stay.

Just to be sure I'm being very explicate here, modify your code for A1 by inserting line 16 as shown below:
#include <iostream>
#include <string.h>

using namespace std;

class A1 {
public:
	char* p;
	A1(const char* str){
		p = new char(strlen(str)+1);
		strcpy(p,str);
	}

	virtual ~A1(){
		delete p;
                p = NULL;   //delete does NOT change the value of p
	}
};

Open in new window

Now run the code and it will blowup on line 5 of Main.cpp.

At this point, the only question I have is why after calling 's.~A1()' followed immediately by 'printf(s.p)' did apparently nothing print rather than what ever was left in memory that s.p was left pointing at.  I can only GUESS that perhaps the memory it was pointed at after the destructor for 'p' was called that memory was somehow left with either unprintable characters or the memory address contained '0' (NULL).

Otherwise, I would have expected that 'delete p' would have left the text of the initial string alone having simply freed up memory.  If that were happening, then I would expect the output to be:
go Gamaone
go Beta
two

(Note this exact output is because 'go Gama' didn't end with '\n', while the strings for 'one', 'go Beta', and 'two' do.
0
 

Author Closing Comment

by:pvinodp
ID: 40090754
I thank all for your contribution
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question