I have a question about pointers in C++.
I know you can't delete a uninitialized pointer and if you want to use delete, the pointer should be initialized first. But does std::cout somehow "initialize" it?
If I try to run the code below it will crash during the execution.
#include <iostream>
int main (){
int *ptr;
delete ptr;
return 0;
}
This is what I'd expect and I'm fine with it because the pointer is not initialized. However if I try to run the code below it won't crash!
#include <iostream>
int main (){
int *ptr;
std::cout << ptr << std::endl; //This is the new line
delete ptr;
return 0;
}
I know that the pointer ptr is not initialized because I can't assign anything to it, if I add this line before the delete
*ptr = 5;
The program will crash as expected.
Why, then the program won't crash if I use the std::cout before delete? I know cout didn't initialize the pointer, but is this somehow a "pre-initialization"(or something else)?
Thanks!
Ezra
Deleting an uninitialized pointer is undefined behavior.
Undefined behavior may crash your program, if you are lucky. You were unlucky, and your program did not crash.
In this case, when you call delete ptr, the compiler knows that the ptr is garbage. Perhaps it just calls delete with whatever value is handy, and if you use cout, nullptr just coincidentally happens to be that value.
Related
This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 4 years ago.
In the below code, memory is allocated for an integer and later a shallow copy is being made and finally delete is being called on it. How does it still print 23 as the output and why doesn't the delete call on q, cause a run time exception.
#include <iostream>
using namespace std;
int main() {
int* p = new int(23);
int* q = p;
delete p;
cout << *p << endl;
delete q;
return 0;
}
Undefined behaviour means anything can happen.
It might crash.
It might crash your car.
It might crash your brain.
It might crash Sagittarius A* into your brain.
It might crash your brain into your car, then crash them both into Sagittarius A*.
It might appear to work.
But it's still undefined.
Don't expect results.
I am pretty new to C++, and while getting started I got stuck on a frustrating problem concerning pointers. Consider the following code:
#include <iostream>
using namespace std;
int main (){
int* mypointer;
*mypointer = 1;
cout << "Whats wrong";
}
It crashes during runtime. I suspect it has to do with the pointer assignment. But after commenting out the cout statement, the program executes. By assigning the pointer as
int* mypointer, myvar;
myvar = 1;
mypointer = &myvar;
the program runs, and I can print the value of the pointer as:
cout << "value of pointer: " << *mypointer;
I draw the conclusion that this would be the correct usage of a pointer.
BUT: Why does the following code execute??:
#include <iostream>
#include <stdio.h>
using namespace std;
int main (){
int* mypointer;
*mypointer = 1;
printf("This works!\n");
printf("I can even print the value mypointer is pointing to: %i",*mypointer);
}
Simply using printf?? I would really appreciate an explanation guys!
The code executes because, just by chance, your compiler has managed to optimise the program down enough that the 1 is "hardcoded" into the printf call.
It would probably have done this anyway, rendering both the original int and the pointer irrelevant, but in this instance it's not reflecting the fact that the pointer was broken and there wasn't an original int.
so, strictly speaking, this doesn't even reflect the semantics of the program: as you've spotted, assigning a value to an int that doesn't exist (through an uninitialised or otherwise invalid pointer) is nonsense and results in undefined behaviour.
But that's the nature of undefined behaviour: anything can happen! The authors of your compiler are making the most of that, by realising that they don't have to write any code to make this case work logically. Because it's you who violated the C++ contract. :)
I am a c++ learner. Others told me "uninitiatied pointer may point to anywhere". How to prove that by code.?I made a little test code but my uninitiatied pointer always point to 0. In which case it does not point to 0? Thanks
#include <iostream>
using namespace std;
int main() {
int* p;
printf("%d\n", p);
char* p1;
printf("%d\n", p1);
return 0;
}
Any uninitialized variable by definition has an indeterminate value until a value is supplied, and even accessing it is undefined. Because this is the grey-area of undefined behaviour, there's no way you can guarantee that an uninitialized pointer will be anything other than 0.
Anything you write to demonstrate this would be dictated by the compiler and system you are running on.
If you really want to, you can try writing a function that fills up a local array with garbage values, and create another function that defines an uninitialized pointer and prints it. Run the second function after the first in your main() and you might see it.
Edit: For you curiosity, I exhibited the behavior with VS2015 on my system with this code:
void f1()
{
// junk
char arr[24];
for (char& c : arr) c = 1;
}
void f2()
{
// uninitialized
int* ptr[4];
std::cout << (std::uintptr_t)ptr[1] << std::endl;
}
int main()
{
f1();
f2();
return 0;
}
Which prints 16843009 (0x01010101). But again, this is all undefined behaviour.
Well, I think it is not worth to prove this question, because a good coding style should be used and this say's: Initialise all variables! One example: If you "free" a pointer, just give them a value like in this example:
char *p=NULL; // yes, this is not needed but do it! later you may change your program an add code beneath this line...
p=(char *)malloc(512);
...
free(p);
p=NULL;
That is a safe and good style. Also if you use free(p) again by accident, it will not crash your program ! In this example - if you don't set NULL to p after doing a free(), your can use the pointer by mistake again and your program would try to address already freed memory - this will crash your program or (more bad) may end in strange results.
So don't waste time on you question about a case where pointers do not point to NULL. Just set values to your variables (pointers) ! :-)
It depends on the compiler. Your code executed on an old MSVC2008 displays in release mode (plain random):
1955116784
1955116784
and in debug mode (after croaking for using unitialized pointer usage):
-858993460
-858993460
because that implementation sets uninitialized pointers to 0xcccccccc in debug mode to detect their usage.
The standard says that using an uninitialized pointer leads to undefined behaviour. That means that from the standard anything can happen. But a particular implementation is free to do whatever it wants:
yours happen to set the pointers to 0 (but you should not rely on it unless it is documented in the implementation documentation)
MSVC in debug mode sets the pointer to 0xcccccccc in debug mode but AFAIK does not document it (*), so we still cannot rely on it
(*) at least I could not find any reference...
I'm trying to get segment fault, but I can't get it and I wonder why.
#include <iostream>
using namespace std;
class A{
public:
char *field_;
A(char *field):field_(field) {
// I believe(suppose) that it's equal to
// field_ = field;
// so actual initial string wasn't copied, only a pointer to it
}
void show() {
cout<<field_<<"\n";
}
};
int main(){
A *obj;
{
char *line="I should be freed";
obj = new (nothrow) A(line);
}
// After exiting from the previous scope,
// char *line variable should be freed.
// Constructor of class A didn't make byte for byte
//copying, so we cannot have
// access to it for sure
for(int i=0;i<4;i++) // trying to clear stack and erase char *line variable
char something[10000];
obj->show(); // and it works correctly!!!! why?
delete obj;
return 0;
}
Ok, as I understand it works correctly only because that string wasn't freed from memory.
I.e. we are just lucky.
And here we have undefined behaviour. Am I right?
Thank you in advance!!
You won't get a segmentation fault because there are no invalid memory references made by your program. I'd guess you think that ""I should be freed" is created on stack and then destroyed or freed somehow, and that is a wrong assumption because that is a constant string literal and it is placed into program data segment and is "alive" for the life of your program.
And even if it was allocated dynamically and freed automatically upon leaving the scope, you still cannot expect your program to receive SIGSEGV in that case. Because undefined behavior does not always result in segmentation faults.
Also, try to never write char *data = "blah-blah";. String literals are assumed to always be constant and trying to modify them is undefined behavior. Though people still hack around this sometimes.
char *line = "I should be freed";
You still see the content because the string literals has static storage duration. Here the string literal I should be freed resides in read only location and is freed once the program execution completes.
The program has no undefined behavior.
Where does the pointer returned by calling string::c_str() point to ? In the following code snippet, I thought I will give get a segmentation fault but it gives me the correct output. If the pointer returned by string::c_str() points to an internal location inside the string object, then when the function returns and the object destructor gets invoked, I should get an invalid memory access.
#include <iostream>
#include <string>
using namespace std;
const char* func()
{
string str("test");
return str.c_str();
}
int main()
{
const char* p = func();
cout << p << endl;
return 0;
}
Output: test
Compiler: g++ 4.3.3
Platform: ubuntu 2.6.28-19
Where does the pointer returned by calling string::c_str() point to?
It points to some place in memory where a null-terminated string containing the contents of the std::string is located.
The pointer is only valid until the std::string is modified or destroyed. It is also potentially invalidated if you call c_str() or data() again.
Basically, your safest bet is to assume the pointer obtained from c_str() is invalidated the next time you do something to the std::string object.
I should get an invalid memory access.
No, you get undefined behavior. You might get a memory access error of some kind (like a segmentation fault), but your program also might appear to continue running correctly. It might appear to work one time you run your program but fail the next.
What would you expect this to print out?
#include <iostream>
#include <string>
int main()
{
int* test = new int[20];
test[15] = 5;
std::cout << test[15] << "\n";
delete[] test;
std::cout << test[15] << "\n";
return 0;
}
In release mode on VS 2010, I get this result:
5
5
Deallocated memory doesn't necessarily throw an exception when you try to access it. The value doesn't necessarily get re-written, either. (Interestingly enough, if I change the compile to debug mode, the compiler overwrites the value with -572662307).
What happens when you try to access it is undefined by the standard. That means the compiler can do whatever it feels like doing, or choose to do nothing. (Or crash your program, or blow up the universe...)