Hi can someone tell why in Linux and windows the same problem occurs :
#include <iostream>
using namespace std;
class A
{
private:
int _dmember;
public:
void func()
{
cout<<"Inside A!! "<<endl;
cout<<_dmember; // crash when reach here.
}
};
int main ()
{
A* a= NULL;
a->func(); // prints "Inside A!!!"
return 1;
}
can someone tell why this weird behivior occurs ? i mean ,
the a->func() was not supposed to get inside the func() ,...?
this is unwated behavior ,
why the above behivor occurs?
EDIT: Of course , a* =null was intentionaly!! so for all who answered "this is undefined behavior" or "you should never try to call a function on a NULL pointer !!", come on.... that was the point. and this behavior was explained correctly by some of you.
This is undefined behaviour. You must never call functions on a null pointer.
With that out of the way, let's answer the question I think you're asking: why do we get partway into the function anyway?
When you are invoking UB, the compiler is free to do anything, so it's allowed to emit code that works anyway. That's what happens on some (many?) systems in this particular case.
The reason that you're able to call the function on a null pointer successfully is that your compilers don't store the function "in" the object. Rather, the above code is interpreted somewhat like this:
class A {
int _dmember;
};
void A::func(A *this) {
cout << "Inside A!!" << endl;
cout << this->_dmember << endl;
}
int main() {
A *a = ...;
A::func(a);
}
So, you see there is nothing that actually prevents you from calling a function on a null pointer; it'll just invoke the body of the function, with the this pointer set to null. But as soon as the function tries to dereference the this pointer by accessing a field inside the class, the operating system steps in and kills your program for illegal memory access (called segmentation fault on Linux, access violation on Windows).
Nitpicker's corner: Virtual functions are a different story.
Undefined behavior because you are accessing a NULL pointer:
A* a= NULL;
a->func(); // is not defined by the language
Note that even if func() didn't try to access a member variable, the behavior still is undefined. For example, the following code could run without errors, but it is not correct:
func()
{
cout<<"Inside A!! "<<endl;
}
EDIT: With my full respect, C++ doesn't suck!
What you need is a smart pointer, not a raw pointer. As my professor says always, if you don't know what you are doing in C/C++, it is better not to do it!
Use boost::scoped_ptr, and enjoy exception safety, automatic memory management, zero overhead and NULL checking:
struct test
{
int var;
void fun()
{
std::cout << var;
}
};
int main()
{
boost::scoped_ptr<test> p(NULL);
p->fun(); // Assertion will fail, Happy debugging :)
}
Dereferencing a null pointer is undefined behaviour.
Everything could happen, so don't do it.
You must check that the pointer is valid before dereferencig it. this pointer cannot be null so you wouldn't avoid the undefined behaviour.
Most compilers just pass the pointer to the class as the first parameter (The this pointer). If you don't go on to de-reference the this pointer then you are not actually going to cause a crash. Your this pointer, inside the functiom, will simply be NULL.
As AraK pointed out this is undefined behaviour so your mileage mat vary...
Aren't you supposed to allocate a memory for your pointer? I just wonder what is the intention to call a function of a NULL pointer? It's supposed to crash immediately. It doesn't crash on the line where you don't call to A member _dmember,but the moment you call it your function crashes cause the object is simply not allocated. _dmember points on undefined memory... That's why it crashes
Its a null pointer, you simply can't define what should happen if we call a function on it.
Any pointer variable is supposed to point to some object.
Your declaration A * a = NULL;
does not point anywhere and so will not yield the results as it should.
You can however try this
A * a = NULL;
A b;
a=&b;
a->func();
this will yield the output.
Since there are no virtual functions in your class, it's easier here to think about what C code would be generated to represent this type. Approximately:
#include <stdio.h>
typedef struct
{
int d_;
} A;
FILE* print_a_to(A* a, FILE* dest)
{
return fprintf(dest, "Inside A!! \n") < 0 ||
fprintf(dest, "%d", a->d_) < 0 ?
NULL :
dest;
}
int main(int argc, char* argv[])
{
A* a = NULL;
return NULL == print_a_to(a, stdout) ?
-1 :
0;
}
Look at the second line of function print_a_to; see the dereferencing of pointer a? Per the first line of function main, you're passing NULL as the value of pointer a. Dereferencing a null pointer here is equivalent to calling a member function on your class that needs access to its member variables through a null pointer.
if i was'nt clear,
i am not trying to do deliberately below:
A* a=NULL;
a->f();
i wrote that code just to check why is it working , and ofcourse i was disappointed and my reason to be disapointed is that i debug very big program in Redhat-Linux , through log-files concept( meaning - Printing Entering,Exiting from functions to logs, including printing imporant values).
AND, on my way on the logs i hoped that if im on specific STACK of function calls i hoped at least the instances operating these functions are alive, but as i discovered and disapointed its not ought to be , which for me disapointement because it makes the debug through log files even more difficult.
I hope you described the symptoms exactly as what you saw. I tried on both Windows and Linux. Linux gives a segment fault, and Windows displays the error dialog.
The address area around 0x0 is protected by Windows and Linux. Reading and writing in this memory area will cause the OS throws an exception. Your application can catch the exception. Most application do not, and OS default handling routine is to print some error message and terminate the program.
One may ask why the message ""Inside A!! " is printed before termination. The answer is that at backend, C++ compiler converts class methods into procedure calls. This step does not involve pointer dereference. You can think that the result look like this:
void A_func(A* a)
{
cout<<"Inside A!! "<<endl;
cout<<a->_dmember; // crash when reach here.
}
A* a = NULL;
A_func(a);
The dereference of NULL pointer happened at the second statement. So the first statement was executed just fine.
the point is that the -> operator on class object (with no vtable) is not a dereference of the pointer
a->foo()
is really shorthand for
A::foo(a)
where the first param gets transformed into the this pointer. Its when u try to deref 'this' by referring to member variable that things go bad.
Related
The code below works fine, but if I try to access the private member variable m_sal in the function fun(), it leads to segmentation fault.
Can any one explain what's the reason ?
class Emp
{
int m_sal;
public :
void fun(char* name)
{
std::cout<<"Name :"<<name<<std::endl;
}
};
int main()
{
Emp *e = NULL;
e->fun("Hi");
return 0;
}
Calling a method by a NULL pointer - as you are doing - is undefined behaviour. So it may crash, not crash, do anything.
First might want to change your method's signature to read
void fun (const char* name) const;
Converting from "Hi" to char * is deprecated and const correctness highly recommended. Your crash is caused as people mentioned by calling your method on a null pointer. Try
Emp * e = new Emp;
e->fun("Hi");
instead.
Of course it crashes.
Emp *e = NULL;
creates a pointer which happens to be a null pointer (because of = NULL , but I am sure many of us would prefer = nullptr), so there is no memory allocated for the object it is pointing to. You need to create an object this pointer will point to:
Emp* e = new Emp;
and now you can use it.
The exact reason for the crash is that the application is trying to fetch a value from a very low memory address (pointer's value is 0, for some cases add a few padding bytes maybe for the correct memory layout of the C++ object, but highly possible in this case it just wants to read the memory at address 0) which in most cases and OS's is reserved to be used by the system.
In your code, e is a pointer, not an actual instance of an object. You can either have:
Emp e;
e.fun("Hi");
//No need to clean up stack variable
OR
Emp *e = new Emp;
e->fun("Hi");
delete e; //don't forget to clean up!
What you have is undefined behavior because of using a null pointer to call a function.
Any body has any idea why this code print a and not b?
I tested that value of mainArea.root->rightBro changes when i cout something. but why?
#include<iostream>
using namespace std;
struct triangle{
triangle *rightBro;
};
struct area{
triangle *root;
} mainArea;
void initialize(){
triangle root;
mainArea.root = &root;
}
int main()
{
initialize();
mainArea.root->rightBro = NULL ;
if (mainArea.root->rightBro == NULL) cout << "a" << endl;
if (mainArea.root->rightBro == NULL) cout << "b" << endl;
return 0;
}
You are storing a pointer to a local variable from within initialize. After the function returns that memory address is no longer valid to access through the pointer -- your program invokes undefined behavior (UB) when it dereferences mainArea.root inside main.
By definition, when UB is invoked anything can happen. What you see is some version of anything.
For practical programming purposes, please stop reading here. If you are curious why you are getting specifically this type of behavior, here's an explanation:
What happens in practice is that mainArea.root is left pointing to an "unused" address on the stack just after the stack frame for main. When you invoke operator<< a new stack frame is allocated, which overlaps the memory pointed to by mainArea.root. operator<<'s (stack-allocated) local variables overwrite the contents of that memory, which from the viewpoint of main results in seeing modified values.
This:
void initialize(){
triangle root;
mainArea.root = &root;
}
Is causing undefined behavior.
The variable triangle root; only lasts as long as the function is being executed. Once the function returns it no longer exists. Thus mainArea.root points at random mememory that can be re-used for anything.
Thus any use of mainArea.root after the function exits is undefined behavior. Meaning the application can do anything.
Consider the following c++ code:
class test
{
public:
int val;
test():val(0){}
~test()
{
cout << "Destructor called\n";
}
};
int main()
{
test obj;
test *ptr = &obj;
delete ptr;
cout << obj.val << endl;
return 0;
}
I know delete should be called only on dynamically allocated objects but what would happen to obj now ?
Ok I get that we are not supposed to do such a thing, now if i am writing the following implementation of a smart pointer, how can i make sure that such a thing does't happen.
class smart_ptr
{
public:
int *ref;
int *cnt;
smart_ptr(int *ptr)
{
ref = ptr;
cnt = new int(1);
}
smart_ptr& operator=(smart_ptr &smptr)
{
if(this != &smptr)
{
// House keeping
(*cnt)--;
if(*cnt == 0)
{
delete ref;
delete cnt;
ref = 0;
cnt = 0;
}
// Now update
ref = smptr.ref;
cnt = smptr.cnt;
(*cnt)++;
}
return *this;
}
~smart_ptr()
{
(*cnt)--;
if(*cnt == 0)
{
delete ref;
delete cnt;
ref = 0;
cnt = 0;
}
}
};
You've asked two distinct questions in your post. I'll answer them separately.
but what would happen to obj now ?
The behavior of your program is undefined. The C++ standard makes no comment on what happens to obj now. In fact, the standard makes no comment what your program does before the error, either. It simply is not defined.
Perhaps your compiler vendor makes a commitment to what happens, perhaps you can examine the assembly and predict what will happen, but C++, per se, does not define what happens.
Practially speaking1, you will likely get a warning message from your standard library, or you will get a seg fault, or both.
1: Assuming that you are running in either Windows or a UNIX-like system with an MMU. Other rules apply to other compilers and OSes.
how can i make sure that [deleteing a stack variable] doesn't happen.
Never initialize smart_ptr with the address of a stack variable. One way to do that is to document the interface to smart_ptr. Another way is to redefine the interface so that the user never passes a pointer to smart_ptr; make smart_ptr responsible for invoking new.
Your code has undefined behaviour because you used delete on a pointer that was not allocated with new. This means anything could happen and it's impossible to say what would happen to obj.
I would guess that on most platforms your code would crash.
Delete's trying to get access to obj space in memory, but opperation system don't allow to do this and throws (core dumped) exception.
It's undefined what will happen so you can't say much. The best you can do is speculate for particular implementations/compilers.
It's not just undefined behavior, like stated in other answers. This will almost certainly crash.
The first issue is with attempting to free a stack variable.
The second issue will occur upon program termination, when test destructor will be called for obj.
This is regarding deletion of this pointer for an object allocated on heap.Program is as follows,
class Sample{
private:
int m_value1;
int m_value2;
public:
Sample();
void setValues(int m_value1, int m_value2);
void display();
};
Sample::Sample(){
this->m_value1 = 0;
this->m_value2 = 0;
}
void Sample::setValues(int m_value1, int m_value2){
this->m_value1= m_value1;
this->m_value2 = m_value2;
display();
if(this != NULL)
{
cout <<"Deleting this pointer!"<<endl;
delete this;
cout <<"this->m_value1 is "<<this->m_value1<<endl;
cout <<"this->m_value2 is "<<this->m_value2<<endl;
}
}
void Sample::display(){
cout <<"Values are "<<this->m_value1<<" and "<<this->m_value2<<endl;
}
int main(){
Sample *obj1 = new Sample();;
obj1->setValues(4,6);
obj1->display();
getch();
}
OUTPUT:
Values are 4 and 6
Deleting this pointer!
this->m_value1 is 65535
this->m_value2 is 6
Values are 65535 and 6
Why does the value for m_value1 disappear whereas it stays for the other variable m_value2?
Accessing member variables after delete this is undefined behavior - anything can happen, including unexpected data being read, program crashing or anything else. The object has been destroyed and deallocated and you try to dereference an invalid pointer. Once delete this has happened - don't try to access the member variables, don't try t call member functions and don't do anything else (including comparing or casting) to this pointer.
Why does the value for m_value1 disappear whereas it stays for the other variable m_value2?
You are accessing memory after you deleted it. That means you are invoking undefined behavior.
So anything might happen, and your observation is as right or wrong as anything else.
What's likely going on is that the part of memory where m_value1 was stored is reused for something else, whilst the storage for m_value2 has not been used for something else (yet).
It's a matter of chance, probably the operator<< or whatever your do after deleting this allocates enough memory to overwrite the one and not the other.
But when you do something that shouldn't be done you should not rely on any particular consequences.
Dangerous and unpredictable outputs expected including system crash!
Do not delete location pointed to by this directly. its not a good programming practice. and don't use memory after deleting. and even if u have to put it inside an assert()
this != NULL // this will never be NULL if used properly.
I am trying a code which Goes like this:-
class test{
int test_int;
public:
virtual int show()
{
return test_int;
}
void set_int(int data){
std::cout<<"received data "<< data <<endl;
test_int = data;
}
};
int main()
{
test *ptr=new test();
ptr=NULL;
ptr->set_int(5);
return 0;
}
Now the problem i am facing is my program after printing the data which i am sending through set_int function got printed but the program crashes just after the completition of the function(set_int).
Am i doing any mistake that is not according to the language standards?
TIA.
Am i doing any mistake that is not according to the language standards?
Yes, you are.
You may not call member functions on a pointer that does not point to a valid object of that type. A null pointer never points to a valid object.
The trivial fix here is to remove the line ptr=NULL;. That way ptr still points to an object when the member function is invoked. This also allows you to fix the memory leak by deleting the pointer later. As a sidenote: avoid manual memory management.
You have pointer to test (test*) set to dynamicaly allocated memory representing instance of that class.
Right after that, you wrote "Nah, I do not need it anymore" and you forget where that newly allocated memory was.
Finally, you are trying to access an object on address 0, which is an invalid operation and will cause runtime error.
You probably meant to do this
int main()
{
test *ptr = new test();
ptr->set_int(5);
// ptr = NULL; // wont free the memory allocated by new
delete ptr; // memory deallocation
ptr = NULL; // now we can safely forget that address (which is now invalid anyways)
return 0;
}