This code must have crashed....but works fine

H

hsharsha

Consider the below code snippet:

#include <iostream>
using namespace::std;

class myclass
{
public:
myclass() {
cout << "constructor" << endl;
}
~myclass() {
cout << "destructor" << endl;
}
void func() {
cout << "func" << endl;
}
};

int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.
the code doesnt crash and the output will be like
constructor
destructor
func

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

anybody has an idea about it ??????????

regards,
Harsha.
 
T

Thomas Tutone

Consider the below code snippet:

#include <iostream>
using namespace::std;

class myclass
{
public:
myclass() {
cout << "constructor" << endl;
}
~myclass() {
cout << "destructor" << endl;
}
void func() {
cout << "func" << endl;
}
};

int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine

Actually, that merely results in undefined behavior.
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.
the code doesnt crash and the output will be like
constructor
destructor
func

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

anybody has an idea about it ??????????

When you have undefined behavior, that means anything could happen.
For example (1) the program might crash, (2) the program might work as
if you had a valid object (since your class has no members and
therefore the null pointer is never dereferenced), or (3) the program
might print "Harsha uses far too many question marks ('?') in his
postings" on your console over and over again. If it's undefined, you
just don't know.

Best regards,

Tom
 
T

Thomas J. Gritzan

Consider the below code snippet: [snip]
int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.

Where did you get that compiler? MS C++ is at version 8.0.
the code doesnt crash and the output will be like
constructor
destructor
func

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

Your code invokes undefined behaviour by dereferencing a null-pointer.
Undefined means, the compiler is free to do everything it wants: It might
appear to work this time, or it might format your hard disk.
 
P

Philip Potter

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

anybody has an idea about it ??????????

Unfortunately, C++ doesn't have strict rules about what happens when you do
something naughty like this. When you call obj->func(); with obj==NULL, the
behaviour is undefined. That means that it may, fortuitously, work exactly
as expected; but this is no guarantee that it works on any other compiler.

You may get different results if you add a variable to myclass and access it
from func(); you may not. Either way, you are correct, this code is wrong,
but the compiler may not be able to warn you about it.

Philip
 
R

Rolf Magnus

Consider the below code snippet:

#include <iostream>
using namespace::std;

class myclass
{
public:
myclass() {
cout << "constructor" << endl;
}
~myclass() {
cout << "destructor" << endl;
}
void func() {
cout << "func" << endl;
}
};

int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine

The C++ standard doesn't require any code to 'crash'.
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.
the code doesnt crash and the output will be like
constructor
destructor
func

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

What makes you think there is no other possible outcome than a 'crash'?
anybody has an idea about it ??????????

Try to repair your '?' key. It seems broken.
 
H

hsharsha

Philip said:
Unfortunately, C++ doesn't have strict rules about what happens when you do
something naughty like this. When you call obj->func(); with obj==NULL, the
behaviour is undefined. That means that it may, fortuitously, work exactly
as expected; but this is no guarantee that it works on any other compiler.

You may get different results if you add a variable to myclass and access it
from func(); you may not. Either way, you are correct, this code is wrong,
but the compiler may not be able to warn you about it.

Philip

i tried it in microsoft cl 6.0, 7.0 and g++ (suprisingly same
behaviour). all the three give the same result. if its undefined, then
there must be some variations in the output, but its the same. i am
really confused.
i even tried adding a variable to the class, but the result was the
same. u guys can try it on any compiler and let me know if possible. i
doubt something in this.
 
H

Howard

i tried it in microsoft cl 6.0, 7.0 and g++ (suprisingly same
behaviour). all the three give the same result. if its undefined, then
there must be some variations in the output, but its the same. i am
really confused.
i even tried adding a variable to the class, but the result was the
same. u guys can try it on any compiler and let me know if possible. i
doubt something in this.

The term "undefined" means that the Standard for C++ does not define what
the results should be. It is simply up to to you to avoid undefined
behavior at all times. It makes no difference if it happens to do the exact
same thing on every compiler and every computer in existence. It's improper
to do that, and the results are not specified by the Standard. You should
not rely on it working, or crashing, or on any specific behavior at all.
Just don't do that! :)

-Howard
 
R

Rolf Magnus

i tried it in microsoft cl 6.0, 7.0 and g++ (suprisingly same
behaviour). all the three give the same result. if its undefined, then
there must be some variations in the output,

No. "Undefined" means that nothing is required. Not even that every compiler
behaves differently.
but its the same. i am really confused.

Why? It's simple. If you invoke undefined behavior, don't expect any specifc
or unspecific behavior. Just don't expect anything.
 
B

Bo Persson

Thomas J. Gritzan said:
Consider the below code snippet: [snip]
int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.

Where did you get that compiler? MS C++ is at version 8.0.

No, it's the Visual Studio that is at version 8.0 (or 2005), using the
interesting scheme 1, 2, oops, 4, etc.

The current C++ compiler is at version 14.0, counting its ancestry all
the way back to the very first (non-Visual) MS C compiler, version 3.0
(don't ask :).


To be somewhat on topic, I must also add that undefined behaviour
doesn't at all mean "must crash", as other posters have pointed out.
The really nasty result is "seems to work".


Bo Persson
 
S

Salt_Peter

Consider the below code snippet:

#include <iostream>
using namespace::std;

class myclass
{
public:
myclass() {
cout << "constructor" << endl;
}
~myclass() {
cout << "destructor" << endl;
}
void func() {
cout << "func" << endl;
}
};

int main(void) {
myclass *obj = new myclass();

....should be...
myclass* obj = new myclass;
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.
the code doesnt crash and the output will be like
constructor
destructor
func

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

Its undefined behaviour. Meaning that the result can't be guarenteed.
Undefined behaviour is often not a crash. Yet if you understand and
apply the concepts - UB is an important subject because
just_because_it_works does not mean its valid.

The only reason you never saw the "crash" is because the func() member
function isn't doing any work. Don't forget that the 'this' parameter
is passed to all non-const member functions. The fact that func() fails
to generate an access diagnostic is only because the obj's internals
are not being accessed.
Consider:

class myclass
{
int m_n;
public:
myclass() : m_n( 0 )
{
std::cout << "constructor" << std::endl;
}
~myclass()
{
std::cout << "destructor" << std::endl;
}
void func()
{
std::cout << "func where m_n = " << m_n << std::endl;
}
};

The above class now does generate a crash when the zapped obj's access
is attempted...
The fact that the original did not crash is irrelevent, its still UB.
Undefined behaviour is about concepts, not results.
 
J

Jack Klein

Thomas J. Gritzan said:
Consider the below code snippet: [snip]
int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.

Where did you get that compiler? MS C++ is at version 8.0.

No, it's the Visual Studio that is at version 8.0 (or 2005), using the
interesting scheme 1, 2, oops, 4, etc.

The current C++ compiler is at version 14.0, counting its ancestry all
the way back to the very first (non-Visual) MS C compiler, version 3.0
(don't ask :).

Since you opened the off-topic can of worms, MS C compiler versions
prior to 3.0 were repackaged version of Lattice C.

I made a good living for quite a few years with Lattice C 2.14.
 
M

Maett

Thomas said:
Consider the below code snippet: [snip]
int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.

Where did you get that compiler? MS C++ is at version 8.0.

I guess the OP meant the macro _MSC_VER which the compiler sets to
1200 for MSVC++ 6
1300 for version 7.0 (.NET 2002)
1310 for version 7.1 (.NET 2003)
1400 for version 8.0 (2005)

Maett
 
R

Rolf Magnus

Salt_Peter said:
...should be...
myclass* obj = new myclass;
Why?


Its undefined behaviour. Meaning that the result can't be guarenteed.
Undefined behaviour is often not a crash. Yet if you understand and
apply the concepts - UB is an important subject because
just_because_it_works does not mean its valid.

The only reason you never saw the "crash" is because the func() member
function isn't doing any work. Don't forget that the 'this' parameter
is passed to all non-const member functions. The fact that func() fails
to generate an access diagnostic is only because the obj's internals
are not being accessed.

However, this might be the reason (and typically is), but as you write
above, you can't rely on that, because it's undefined behavior.
 
S

Salt_Peter

Rolf said:

Why not? Since the ctor is a default ctor?
However, this might be the reason (and typically is), but as you write
above, you can't rely on that, because it's undefined behavior.

Its not a question of relying on it. I'm proving that its UB by showing
that an instance of the class is in fact not being accessed, regardless
of the result(s). I'm trying to say: "don't let the result influence
the code's validity". Moreover, i've explained why its UB, not "its UB
cause we said so".

I wish i could find a better word than "concept", maybe "this
particular sequence of events"?

Surely, the concept here is far more important than the result, its the
concept, not the result, that is UB. The language does not dictate that
there is only way good way to code a sequence of events. I think its
far more usefull for the OP to grab the meaning of UB literally. The
English language describes it perfectly : its undefined behaviour,
nothing more, nothing less. Looking for UB should be a tool for the
programmer to write better code, not a detriment nor a dark, mysterious
methodology.

So yes: its UB. But the question is: Why is it UB?
 
J

Jim Langston

Consider the below code snippet:

#include <iostream>
using namespace::std;

class myclass
{
public:
myclass() {
cout << "constructor" << endl;
}
~myclass() {
cout << "destructor" << endl;
}
void func() {
cout << "func" << endl;
}
};

int main(void) {
myclass *obj = new myclass();
delete obj;
obj = NULL; // obj = (myclass*)0;
obj->func(); //..............must be a crash..... but works fine
return 0;
}

i tried the above code in Microsoft compiler 12.0, 13.0 and g++.
the code doesnt crash and the output will be like
constructor
destructor
func

i really dont know how when obj is null, obj->func() is valid and not
crashing ?????????????/

anybody has an idea about it ??????????

Yes. It's just the implementation. Lets take a look at your calls one by
one.

myclass* obj = new myclass();
This makes obj a pointer to myclass and allocates the memory for it, which
runs the constructor.

delete obj;
This runs the destructor for MyClass and releases the memory.

obj = NULL;
This makes the obj point to nothing.

obj->func();
Okay, so what happens here? The compiler will call the function func()
(which there is only one copy of for no matter how many instances of
MyClass), which gets passed the address of obj (NULL in this case) as the
this pointer.
func() is run, and simply consists of a cout statement, which works.

If you have your func() attempt to output a variable located in MyClass,
however you will get a memory read error (sig fault on linux, memory
exception reading location 0x0000XXXX in windows).

If you do not set
obj = NULL;
it may appear to work sometimes because the memory hasn't been allocated and
changed by another object yet, but othertimes it may give you bad output or
other errors (depending on if another object has allocated the memory and
changed it, or perhaps the page the memory is on has been swapped out
because no object is using that memory, etc..).

Notice, I am only explaining *why* it did not crash for you. I am not
saying you should do this. This is a Bad Idea. But I find that
understanding what is going on beneight the covers sometimes helps me
understand code better.
 

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,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top