stack variable lifetime curious example [duplicate] - c++

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
Please consider this simple example:
#include <iostream>
const int CALLS_N = 3;
int * hackPointer;
void test()
{
static int callCounter = 0;
int local = callCounter++;
hackPointer = &local;
}
int main()
{
for(int i = 0; i < CALLS_N; i++)
{
test();
std::cout << *hackPointer << "(" << hackPointer << ")";
std::cout << *hackPointer << "(" << hackPointer << ")";
std::cout << std::endl;
}
}
The output (VS2010, MinGW without optimization) has the same structure:
0(X) Y(X)
1(X) Y(X)
2(X) Y(X)
...
[CALLS_N](X) Y(X)
where X - some address in memory, Y - some rubbish number.
What is done here is the case of undefined behaviour. However I want to understand why there is such behaviour in current conditions (and it is rather stable for two compilers).
It seems that after test() call first read of hackPointer leads to valid memory, but second successive instant read of it leads to rubbish. Also on any call address of local is the same. I always thought that memory for stack variable is allocated on every function call and is released after return but I can't explain output of the program from this point of view.

"Releasing" automatic storage doesn't make the memory go away, or change the pattern of bits stored there. It just makes it available for reuse, and causes undefined behaviour if you try to access the object that used to be there.
Immediately after returning from the function, the memory occupied by the local probably hasn't been overwritten, so reading it will probably give the value that was assigned within the function.
After calling another function (in this case, operator<<()), the memory is likely to have been reused for a variable within that function, so probably has a different value.

You are quite right that this is undefined behaviour.
That aside, what's happening is that std::cout << *hackPointer involves a function call: operator<<() gets called after the value of *hackPointer has been read. In all likelihood, operator<<() uses its own local variables that end up on the stack where local was, wiping out the latter.

Related

When does a non-dynamic variable goes out of scope if being referenced by a pointer? [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 2 years ago.
I'm new to C++ programming and I am having some hard time understanding some concepts.
Take this code as a example:
// Example program
#include <iostream>
class nber
{
int* value;
public:
nber(int n)
{
value = &n;
}
int getNber()
{
return *value;
}
};
int main()
{
nber var(111);
std::cout << "The number is:" << var.getNber() << "\n";
}
As you can see, the nber constructor receives an integer n and passes its address to the "value" pointer. What I expected is to have some kind of unwanted behavior, since the scope of the received integer (n) ends as soon as the constructor end, but the output is:
The number is:111
So the scope didn't end? If it really didn't end, when is the memory used to store the variable n going to be released? Thanks.
The scope did end. What you're seeing is Undefined Behavior - anything can happen. The number could be "purple", as far as the rules say. Or your hard disk could be erased. The latter is a bit rare, though.

How does C++ proceed for += with a variable without value? [duplicate]

This question already has answers here:
What happens when I print an uninitialized variable in C++? [duplicate]
(4 answers)
Closed 6 years ago.
i am currently learning C++ and i had a question about some "weird" things i noticed while testing what i have learnt.
So i use this :
int marc[9];
int sum = 0;
for (int x =0; x < 9; x++) {
marc[x] = x*4;
sum += marc[x];
}
cout << sum << endl;
And i get a normal result which is 144
However, if i changed
int sum = 0;
to
int sum;
I got a crazy result like 19557555002
So i was wondering what is happening in the second case?
Thanks for your answer :)
You are operating on uninitialized memory in the second case. Non-static local variables are not initialized to zero by the runtime like in other languages, if you need sum to have a defined value, you must initialize it yourself. The 19557555002 will be the integer interpretation of any bytes that were present at the memory address allocated for sum.
Further reading: What happens to a declared, uninitialized variable in C? Does it have a value?
Its called an undefined behavior and it happens when you don't initialize your variables.
int sum;
above code can only declare a variable but it doesn't initialize it by default so the variable contains a garbage value.
this creates an uninitialized int int sum;
it can have "garbage" values, and this is exactly what happened to you
how this happens: let's say you use an int x in address y, and sets it to 19557555002. now, lets say you "leave" that address (go out of scope, program terminates, OS takes that memory...) and someone else takes it because he wants to put there a new int. if he just declares his int, without initializing it, his int can be stationed (if the OS so desires...) in address y, that previously used to hold your int, which means in address y, he will find 19557555002. That is what could happen to you if you don't initialize variables.
Memory for local variables is typically allocated on the stack. This means that without some initialization, they will hold some data that was residing there previously.
As others said it is undefined behavior, but practically, on most implementations, it results in effects like this:
void foo()
{
int a = 5;
}
void bar()
{
int b;
std::cout << b;
}
void someCaller()
{
foo();
bar();
}
On most implementations, this will usually result in the printing of 5 on the stdout.
Note that some compilers like MSVC initialize all variables in Debug configuration, but usually any kind of optimization flags will avoid initializing memory, if not explicitly requested.

Pointers pointing to variables(located on the stack) - C++ [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
I guess this is a very basic question, but even after looking around on the internet for a while I can't seem to find a proper answer to this question.
I will refer to this tutorial on stack/heap:http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html
Let's say I write the following code:
void testVoid() {
int testVariable = 5;
}
If I'm not wrong, this function should create a variable located on the stack. As the functions exits, the allocated memory on the stack is deleted - so my variable should also have been deleted by then.
I have learned that pointers in c++ point to the memory location of a variable.
So if the variable pointed to by a pointer is located on the stack, and the stack then is cleared, I would expect not to be able to access original value through the pointer anymore, since the memory location pointed to is is cleared. However, I tested this:
int* pointer;
void testVoid() {
int num = 3;
pointer = &num; // Here I get the memory location of my num-variable
cout << pointer << " : " << *pointer << endl; // I would get the same result if i printed &num
}
int main(int args, char** argv) {
pointer = new int;
testVoid();
cout << pointer << " : " << *pointer << endl; // I can still access the memory of my num-variable
while (true) {}
return 0;
}
After exiting the testVoid()-function, where the variable is created, I can still get the value of the variable using my pointer. So obviously I have misunderstood something regarding how pointers work in c++. Printing &pointer and &num gives me the same memory location, even after testVoid() has finished. What is the reason for this? If the memory pointed to by the pointer were moved to the heap, shouldn't cout<<&num and cout<
And here's the output:
0024F904 : 3
0024F904 : 3
Just because the value goes out of scope does not mean the memory for the value has been overwritten. You just can't rely on it being stable at that point.

Why does this run fine ? (accessing address of an out-of-scope variable) [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
Why does this run fine? (And several times in a row..)
double* p(nullptr);
cout << p << endl; // "00000000"
{
double d(82.);
p = &d;
}
cout << p << endl; // "0029FD98"
// Naughty, dirty, sneaky..
// .. but rather *pure* curiosity after all.. u_u
cout << *p << endl; // "82", first surprise
*p = 83.; // (getting further down the hole..)
cout << *p << endl; // "83", and I almost feel disappointed. :(
Isn't d supposed to be out of scope and 0029FD98 deallocated? Why isn't my OS mad at me? Am I just super lucky?
You are invoking undefined behavior. According to the C++ specification, anything might happen here. Undefined behavior is a very bad thing, because it means you cannot know what your program might do. Avoid it at all costs.
On your particular platform with your particular compiler, this probably works because the variable was allocated on the stack, and the stack memory is not (usually) deallocated while the program is running. As a result, 0029FD98 refers to an address within an allocated region of memory (in this case, the stack). As soon as you call a function, this location is likely to be overwritten with whatever that function needs the stack space for.
On other systems and/or compilers, where local variables and/or the stack might behave or be implemented differently, this could output some random number, or it might crash, or it might output the collective works of Shakespeare.

Returning a reference in C++ [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 6 years ago.
Consider the following code where I am returning double& and a string&. It works fine in the case of a double but not in the case of a string. Why does the behavior differ?
In both cases the compiler does not even throw the Warning: returning address of local variable or temporary as I am returning a reference.
#include <iostream>
#include <string>
using namespace std;
double &getDouble(){
double h = 46.5;
double &refD = h;
return refD;
}
string &getString(){
string str = "Devil Jin";
string &refStr = str;
return refStr;
}
int main(){
double d = getDouble();
cout << "Double = " << d << endl;
string str = getString();
cout << "String = " << str.c_str() << endl;
return 0;
}
Output:
$ ./a.exe
Double = 46.5
String =
You should never return a reference to a local variable no matter what the compiler does or does not do. The compiler may be fooled easily. you should not base the correctness of your code on some warning which may not have fired.
The reason it didn't fire here is probably that you're not literally returning a reference to a local variable, you are returning a variable that is a reference to a local variable. The compiler probably doesn't detect this somewhat more complex situation. It only detects things like:
string &getString(){
string str = "Devil Jin";
return str;
}
The case of the double is simpler because it doesn't involve constructing and destructing a complex object so in this situation the flow control analysis of the compiler probably did a better job at detecting the mistake.
The reference to a double refers to a location that is still physically in memory but no longer on the stack. You're only getting away with it because the memory hasn't been overwritten yet. Whereas the double is a primitive, the string is an object and has a destructor that may be clearing the internal string to a zero length when it falls out of scope. The fact that you aren't getting garbage from your call to c_str() seems to support that.
GCC used to have an extension called Named Returns that let you accomplish the same thing, but allocated the space outside the function. Unfortunately it doesn't exist anymore; I'm not sure why they took it out
Classic case of a Dangling reference in respect to C++.The double variable was not on call stack while returning reference was trying to access it invoking the compiler to set the guarding flags. String however has explicit Garbage Collection mechanism which lets your compiler to overlook the scenario.