This question already has answers here:
Dereferencing a null pointer
(5 answers)
Closed 8 years ago.
class A {
public:
int value = 1;
void foo() { ... };
};
int main() {
A *a = NULL;
int temp = a->value; // Crash!
a->foo(); // OK
}
What happened after I assigned the pointer NULL to a pointer variable? I thought nothing can be done until I allocate a memory to it by new. However, it still can call member function foo(), but crashed when calling member variable.
Could anyone tell me what's going on here? Thanks!
Both invoke Undefined Behavior, irrespective of the behavior you're observing, because when it is UB, anything is possible.
However, one explanation why it does't crash in the second case, possibly because the call:
nullptr->foo(); //a == nullptr, becomes implicit 'this' inside foo()
is translated to:
foo(nullptr); //the implicit 'this' passed as first argument
by the compiler, which seems fine (to the compiler), as you're not accessing any member data inside the function. If you access member data, the chance of getting it crashed increases. The compiler is just being tolerant of your wrongful deeds as long as it can.
de-referencing NULL pointer is undefined behavior. You are unlucky that you got through it in second statement.
In this case, it appears to work because the this pointer, which does not point to a valid object, is not used in foo .If it happened to refer to this there would have been one less post on stack overflow.
Related
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 1 year ago.
While reading about the dangling pointers, I came across some examples and concepts of dangling pointers. Basically, Dangling pointers are those pointers that used to point to some valid memory address but that memory address is no longer valid(local variables, releasing the memory).
So I tried the example:
int* fun(){
int a=100;
return a&;
}
int main() {
int *a =fun();
printf("fun %d",*a);
}
Which gives the error that: address of local variable is returned and it is in sync with dangling pointer concept.
But I slightly modify this code to:
int* fun(){
int a=100;
int* var=&a;
return var;
}
int main() {
int *a =fun();
printf("fun %d",*a);
}
This one works without any error.
My doubt here is that, fun() returns a int pointer and this pointer contains the address of the local variable a. After the function returns back the memory of a should be released then why does this code works without any error.
Also on my system this following don't work:
int main() {
int* x;
{
int y = 3;
x = &y;
}
*x = 56;
printf("jsdf");
}
This being the standard example to demonstrate dangling pointers.
Any one please let me know where my thinking is wrong and what happening behind the scene.
PS: I am using windows10, MinGW compiler with VSCode.
First two examples are equivalent, and in all examples a dangling pointer is used. The compiler doesn’t show you the error in the second example because it is not required to do so, but it is nevertheless invalid, its behavior is undefined. And undefined means undefined, i.e. anything is allowed, including seemingly valid behavior, but more likely data corruption, crashing, or whatever (a.k.a. nasal demons).
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
Is there any thing wrong in the following code?
#include <iostream>
using namespace std;
int* pointer;
void assign() {
int a = 2;
pointer = &a;
}
int main() {
assign();
cout<<*pointer<<endl;
}
According to my knowledge, 'a' exists in stack memory when executing assign(). Hence, after function assign() runs, the memory allocated to 'a' should be released. But in assign(), the address of 'a' is allocated to 'pointer' which exists in data segment. 'pointer' exits in the whole life of this program.
But after assign(), we print out *pointer whose corresponding variable has been released before. Is there any thing wrong will happen? Or is it a undefined behavior?
In fact, the above program can run correctly to print out the right value.
Yes, this is undefined behavior.
The only reason that you "correctly print out the right value" is that because on most common architectures, the formerly vacated address on the stack where the variable existed does not get overwritten or scribbled over by the remaining code in main() that gets executed here.
The code in main() would typically dereference the pointed to the address on the stack before constructing the stack frame for the operator<<() function call.
You get a correct value because the CPU does not yet use the location of variable (a). But if before you print the pointer the CPU need the location of the variable (a), you well get a wrong value.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ delete - It deletes my objects but I can still access the data?
I would like to check if the following simple code has memory leak. In the function, it deletes a pointer and assigns a new object to this pointer. Is this legal? Under g++ compiler, even I deletes the test pointer, I can still access its member, which looks weird for me.
class cTest{
public:
cTest(double _m){
m=_m;
}
~cTest(){}
double m;
};
void function (cTest * test){
delete test;
std::cout<<test->m<<std::endl;
test= new cTest(1.2);
}
int main(){
cTest *t = new cTest(0.1);
std::cout<<t->m<<std::endl;
function (t);
std::cout<<t->m<<std::endl;
delete t;
return 0;
}
it prints out
0.1
0.1
1.2
Whenever you access a pointer after its lifetime has ended (eg. stack allocated object or after a delete) you stumble into undefined behavior, which is even worse than just an error because it may work and suddenly crash just when it decides to.
The pointer is not valid anymore, data is still there because every unnecessary operation is not done in C++, that's why in your situation it works.
Yep it leaks. function doesn't actually modify the value of t in main (because it's parameter is passed by value).
You can often reference deleted memory, but it is a bug (and not reliable).
At the first, there are two mistakes in your code.
pointer is not value.
void function (cTest * test){
delete test;
std::cout<<test->m<<std::endl;
test= new cTest(1.2);
}
test is not overwrited. probably, you expect to re-write pointer value, but it can't.
If you want to do it, use pointer of pointer CTest** test to define argument. Or use return value to give a new pointer value.
#include <iostream>
class cTest{
public:
cTest(double _m){
m=_m;
}
~cTest(){}
double m;
};
void function (cTest** test){
delete *test;
std::cout<<(*test)->m<<std::endl;
*test= new cTest(1.2);
}
int main(){
cTest *t = new cTest(0.1);
std::cout<<t->m<<std::endl;
function (&t);
std::cout<<t->m<<std::endl;
delete t;
return 0;
}
But this code's not good sense, I think.
Yes, there is a leak and double delete of the firstly allocated object. 't' in main continues to point to the first object, as the pointer is not passed to function by reference or double pointer.
I've got a couple of questions regarding pointers. First:
ObjectType *p;
p->writeSomething();
Why is it possible to call a method on an object when the pointer hasn't been initialized? If I run that code I get the output from "writeSomething()" in my console window. Second:
ObjectType *p;
if(p==NULL)
cout<<"Null pointer";//This is printed out
p = new ObjectType;
delete p;
if(p==NULL)
cout<<"Null pointer";
else
cout<<"Pointer is not null";//This is printed out
Why isn't the pointer null in the second if statement and how do I check if a pointer isn't pointing to any memory address? I'm also wondering if there is any way to check if some memory hasn't been released when a program is done executing. For example, if you forget to write 1 delete statement in the code.
The first code is undefined behavior, anything can happen, even appearing to work. It's probably working because the call is resolved statically, and you're not accessing any members of the class.
For the second snippet delete doesn't set the pointer to NULL, it just releases the memory. The pointer is now dangling, as it points to memory you no longer own.
Your code does of course exhibit undefined behaviour, but here's an example of why it may appear possible to call a member function even if there is no object: If the member function doesn't refer to any member objects of the class, then it will never need to access any part of the memory which you haven't initialized. That means, your member function is essentially static.
As you know, member functions can be considered as normal, free functions which have an implicit instance object reference argument. For example, a simple class Foo defined like this,
struct Foo
{
void bar() { std::cout << "Hello\n"; }
};
could be implemented as a single, free function:
void __Foo_bar(Foo * this)
{
std::cout << "Hello\n";
}
Now when you say Foo * p; p->bar();, this amounts to a free function call __Foo_bar(p);. You end up passing an invalid pointer to the function, but since the function never makes use of the pointer, no harm is done.
On the other hand, if your class had a member object, like int Foo::n;, and if the member function was trying to access it, your implementation would try and access this->n, which would very likely cause an immediate problem since you'd actually be dereferencing an invalid pointer.
delete p;
deallocates memory, but it does not change the value of the address stored in p.
There is no method in standard C++ to detect that a pointer is referring to invalid memory. It is your responsibility not to de-reference an invalid pointer.
Your first example is undefined behaviour. One of the possible outcomes of undefined behaviour is that the program works the way you intended it to. Again, it is your responsibility not to write programs with undefined behaviour.
In your code, writeSomething() is probably a non-virtual member function that does not de-reference this which is why it happens to work for you, on your compiler. Most likely if you tried to refer to some member data fields then you would encounter a runtime error.
delete would call upon the destructor of ObjectType followed by de-allocation of memory but it doesn't explicitly makes your pointer NULL
That is something you have to do as a good programming practice.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Returning the address of local or temporary variable
Can a local variable's memory be accessed outside its scope?
#include<iostream>
using namespace std;
int *p = NULL;
void
fun(void){
int i = 10;
p = &i;
}
int
main(void){
fun();
cout<<*p<<endl; //#1
cout<<*p<<endl; //#2
return 0;
}
I think #1 and #2 will output the same, but why #1 output 10 and #2 output a random number?
This is just undefined behavior. You're working with a pointer to a local variable, after that variable has gone out of scope. Anything could happen.
This is indeed a dangling pointer.
You are assigning p to point to an automatic (local) object. Once fun has returned, the object no longer exists, and attempting to access it through p gives undefined behaviour.
If you're interested in why you observe that particular behaviour: on most platforms, the stack frame of fun will still exist until another function is called. So reading p for the first call to << is quite likely to find the old value of i. After calling <<, the old stack frame has most likely been overwritten, so reading p will find an arbitrary value. But none of this is behaviour you can rely on; accessing the dead object could cause a crash, or any other behaviour.
Yes, p becomes a dangling pointer the moment fun() returns.
You are saving a pointer to a variable that is out of scope. Thus, the behavior is undefined. It can print anything, or even crash your application. Or even make your computer explode.
Your function is returning a pointer to something that gets over-written:
int i = 10;
p = &i; // This line
Because i is a local variable.