Solved

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

Posted on 2014-04-09
12
164 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
  • 5
  • 3
  • 3
  • +1
12 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
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
Comment Utility
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
Comment Utility
even if line 4 is wrong.
how can line number 7->  A1 u("go Beta\n"); put data into s?
0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 125 total points
Comment Utility
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 375 total points
Comment Utility
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 74

Expert Comment

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

XD
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 16

Expert Comment

by:HooKooDooKu
Comment Utility
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
Comment Utility
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 375 total points
Comment Utility
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 32

Expert Comment

by:sarabande
Comment Utility
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 375 total points
Comment Utility
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
Comment Utility
I thank all for your contribution
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

728 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now