C++, Accessing a non-global variable declared inside other method [duplicate] - c++

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
This code takes value returned from a function, creates and puts it in a new address space called variable 'b'
int main()
{
int b;
b = topkek();
std::cout << &b;
};
int topkek()
{
int kek = 2;
return kek;
};
Now I understand because variable kek was inside of topkek method I can not access it from main() method. With C++ and pointers, I figured out how I could access a variable declared inside a method even after the method has terminated, look at this code.
int main()
{
int * a;
a = topkek(); //a is now pointing at kek
std::cout << *a; //outputs 2, the value of kek.
*a = 3;
std::cout << *a; //output 3, changed the value of kek.
std::cin >> *a;
};
int * topkek()
{
int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Is this method safe? Would the compiler prevent kek's address space being overwritten later in code because it still understand it's being used?

This is undefined behavior: once the function finishes, accessing a variable inside it by pointer or reference makes the program invalid, and may cause a crash.
It is perfectly valid, however, to access a variable when you go "back" on the stack:
void assign(int* ptr) {
*ptr = 1234;
}
int main() {
int kek = 5;
cout << kek << endl;
assign(&kek);
cout << kek << endl;
}
Note how assign has accessed the value of a local variable declared inside another function. This is legal, because main has not finished at the time the access has happened.

No it is not safe. After your function finished execution, you are not pointing to an int anymore but just to some random place in memory. Its value could be anything since it can be modified elsewhere in your program.

Most definitely not safe. Undefined behavior will result.

When a local variable is "created", the compiler does so by giving the variable some space on the the stack [1]. This space is available for the variable as long as you are inside that function. When the function returns, the space is released, and available for other functions to use. So the address of b in your second code is returning a pointer to memory that will be releasted just after the return finishes.
Try adding something like this:
int foo()
{
int x = 42;
cout << "x = " << x << endl;
return x;
}
and call foo after your call to topkek, and it's pretty certain that the value in kek (or pointed to by kek) will change.
[1] For the pedants: Yes, the C++ standard doesn't specify that there needs to be a stack, or how local variables are supposed to be used, etc, etc. But in general, in nearly all compilers available today, this is how it works.

This will be safe:
int * topkek()
{
static int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};

Locally allocated automatic types will be automatically deallocated when exiting the function scope. The pointer you return will then point to deallocated memory. Accessing this memory will result in undefined behaviour.
int* topkek() {
int kek = 2; // Create a local int kek
int* b = &kek; // Declare pointer to kek
return b; // Return pointer to local variable. <-- Never do this!
}; // kek is destroyed and the returned pointer points to deallocated memory.

This is undefined behavior. After returning from the function, kek does not exist any more, and the pointer returned points into nirvana, to the location where kek once was. Accessing it gives undefined behavior. Undefined behavior means, anything can happen. You could indeed get the value that once was in kek or your application crashes, or you get some garbage value, or your compiler sees fit to order you a pizza online, with extra cheese, please.

This is undefined behavior, kek is a local variable and the memory it resides in will be released once you exit topkek. It may seem like it works but since it is undefined anything can result, it can break at any time and you can not rely on the results.

First, this is definitely unsafe as others have noted. But based on your usage, I think you might actually be trying to define an object. For example, this code might be what you want:
struct topkek{
int kek;
int *operator()() {
kek = 2;
return &kek;
}
};
int main()
{
topkek mykek;
int *a = mykek(); // sets mykek.kek to 2, returns pointer to kek
std::cout << *a;
*a = 3;
std::cout << *a;
std::cin >> *a;
};
This will give you clean access to the underlying kek variable in a totally safe way. You can of course put any code you want into the operator() method.

Related

void* casting get unexpected output

struct mystruct{
int* x;
float *y;
string *z;
mystruct(int* a,float* b, string *c): x(a), y(b), z(c){}
};
void* create(){
int a = 1;
float b = 2.2;
string c = "aaa";
mystruct x(&a, &b, &c);
void* p = &x;
return p;
}
void print(void *p){
mystruct* p1 = static_cast<mystruct*>(p);
cout << *p1->x << " " << *p1->y << " "<<*p1->z<< endl;
}
int main(){
cout << sizeof(mystruct) << endl;
void* p1 = create();
print(p1);
return 0;
}
The output of the code is like: 24
1 2.76648e+19 \203\304 ]\303fffff.\204UH\211\345H\201\354\220H\211}\270H\211.
for which I suppose is: 24 1 2.2 aaa
I guess there is something wrong with the void* pointer casting, but I can not figure out why. Can someone help?
You creating undefined behaviour with this:
void* create(){
int a = 1;
float b = 2.2;
string c = "aaa";
mystruct x(&a, &b, &c);
void* p = &x;
return p;
}
There you initialize a mystruct with pointers to objects in the automatic storage scope (aka a local variable) of create. These objects cease to exist the very moment create is returned from and thus the pointers become invalid. Furthermore you're returning a pointer to a mystruct automatic storage object inside the create function as well. So that's kind of invoking undefined behaviour on top of undefined behaviour.
EDIT here's a proposed solution:
Stop using pointers inside the struct. It doesn't make sense to pass around pointers to int or float anyway, because pointers will always be larger than those. If you pass a pointer or a pointer to a function, either will be passed by copying the value, but with a pointer there's an extra indirection step. Where passing pointers to numeric types makes sense if you want to use them to pass a "reference" where the function can alter the values.
It also makes sense for passing pointers to structures so that not whole structures have to be copied around.
So I suggest you get rid of the pointers at a whole. You apparently do not yet understand how they work, and for that particular task you have there they are the wrong tool anyway.

c++ delete pointer and then access the value of it points to

I just learned pointer and delete pointer in class for C++. I tried this code by my own
# include<iostream>
using namespace std;
int main(){
int num = 10;
int *p = new int;
p = &num;
cout << *p << endl;
delete p;
cout << num << endl;
return 0;
}
After deleting the pointer p, I cannot print the value of num. But if I delete p at the very end of the program, cout << num << endl; will give me 10. Anyone knows where I did run?
You first leaked a pointer
int *p = new int;
p = &num; // You just leaked the above int
then illegally deleted something you did not new
delete p; // p points to num, which you did not new
You have already received a couple of good answers that point out the mistake, but I read a deeper misunderstanding of the allocation and deallocation of heap vs stack variables.
I realised this has become a pretty long post, so maybe if people think it is useful I should put it as a community Wiki somewhere. Hopefully it clarifies some of your confusion though.
Stack
The stack is a limited and fixed size storage. Local variables will be created here if you don't specify otherwise, and they will be automatically cleaned up when they are no longer needed. That means you don't have to explicitly allocate them - they will start existing the moment you declare them. Also you don't have to deallocate them - they will die when they fall out of scope, loosely speaking: when you reach the end brace of the block they are defined in.
int main() {
int a; // variable a is born here
a = 3;
a++;
} // a goes out of scope and is destroyed here
Pointers
A pointer is just a variable, but instead of an int which holds a whole number or a bool which holds a true/false value or a double which holds a floating point, a pointer holds a memory address. You can request the address of a stack variable using the address operator &:
{
int a = 3, b = 4;
int* p = &a; // p's value is the address of b, e.g. 0x89f2ec42
p = &b; // p now holds the address of b, e.g. 0x137f3ed0.
p++; // p now points one address space further, e.g. 0x137f3ed4
cout << p; // Prints 0x137f3ed4
} // Variables a, b and p go out of scope and die
Note that you should not assume that a and b are "next to" each other in memory, or that if p has a "used" address as its value then you can also read and write to the address at p + 1.
As you probably know, you can access the value at the address by using the pointer indirection operator, e.g.
int* p = &a; // Assume similar as above
*p = 8;
cout << a; // prints 8
cout << &a << p; // prints the address of a twice.
Note that even though I am using a pointer to point at another variable, I don't need to clean up anything: p is just another name for a, in a sense, and since both p and what it points to are cleaned up automatically there is nothing for me to do here.
Heap
The heap memory is a different kind of memory, which is in theory unlimited in size. You can create variables here, but you need to tell C++ explicitly that you want to do so. The way to do this is by calling the new operator, e.g. new int will create an integer on the heap and return the address. The only way you can do something sensible with the allocated memory, is save the address this gives you. The way you do this, is store it in a pointer:
int* heapPtr = new int;
and now you can use the pointer to access the memory:
*heapPtr = 3;
cout << heapPtr; // Will print the address of the allocated integer
cout << *heapPtr; // Will print the value at the address, i.e. 3
The thing is that variables created on the heap will keep on living, until you say you don't need them anymore. You do that by calling delete on the address you want to delete. E.g. if new gave you 0x12345678 that memory will be yours until you call delete 0x12345678. So before you exit your scope, you need to call
delete heapPtr;
and you will tell your system that the address 0x12345678 is available again for the next code that comes along and needs space on the heap.
Leaking memory
Now there is a danger here, and that is, that you may lose the handle. For example, consider the following:
void f() {
int* p = new int;
}
int main() {
f();
cout << "Uh oh...";
}
The function f creates a new integer on the heap. However, the pointer p in which you store the address is a local variable which is destroyed as soon as f exits. Once you are back in the main function, you suddenly have no idea anymore where the integer you allocated was living, so you have no way to call delete on it anymore. This means that - at least for the duration of your program - you will have memory that according to your operating system is occupied, so you cannot use it for anything else. If you do this too often, you may run out of memory even though you can't access any of it.
This is one of the errors you are making:
int* p = new int;
allocates a new integer on the heap and stores the address in p, but in the next line
p = &num;
you overwrite that with another address. At this point you lose track of the integer on the heap and you have created a memory leak.
Freeing memory
Aside from freeing memory not often enough (i.e. not instead of once), the other error you can make is freeing it too often. Or, to be more precise, you can make the error of accessing memory after you have told your OS you don't need it anymore. For example, consider the following:
int main() {
int* p = new int;
*p = 10;
delete p; // OK!
*p = 3; // Errr...
}
That last line is very wrong! You have just returned the memory allocated when you called delete, but the address is still stored in p. After you call delete, your OS is allowed to re-allocate the memory at any time - for example, immediately after another thread could call new double and get the same address. At that point, if you write *p = 3 you are therefore writing to memory that is no longer yours which may lead to disaster, if you happen to overwrite the location in memory where the nuke's launch codes are stored, or nothing may happen at all because the memory is never used for anything else before your program ends.
Always release your own memory, and nothing but your own memory
We have concluded the following: memory allocated on the stack is not yours to claim, and not yours to release. Memory allocated on the heap is yours to claim, but you must also release it once and only once.
The following examples are incorrect:
{
int a = 3;
int* p = &a;
delete a;
} // Uh oh... cannot clean up a because it is not ours anymore!
{
int* p = new int;
delete p;
*p = 3; // Uh oh, cannot touch this memory anymore!
delete p; // Uh oh, cannot touch this memory anymore!
}
Why does it print 10?
Well, to be honest, you were just "lucky" there. Actually, the way your operating system manages memory, is generally pretty lazy. When you tell it "I would like some memory" it doesn't zero it for you. That is why it is a bad idea to write
int main() {
int a;
a = a + 3;
cout << a;
}
You get allocated a variable a somewhere in the memory, but the value of a will be whatever was in that memory location. It might be zero, or some random number that depends on how the bits fell when you booted your computer. That is why you should always initialize the variable:
int a = 0;
Similarly, when you say "I don't need this memory" anymore, the OS doesn't zero it. That would be slow and unnecessary: all it needs to do is mark the memory as "free to be re-allocated". So if you give it back and access it immediately afterwards, the probability that it has not been re-allocated yet is pretty large. Therefore
int* p = new int;
*p = 10;
delete p;
cout << *p;
is not guaranteed to print 10. The address p is pointing to may have been (partially) taken (and initialized!) by someone else immediately after the delete. But if it hasn't, the memory will still contain the value 10 there so even though it isn't yours anymore, C++ will still allow you to access it. Basically, when you are using pointers, you are telling it "trust me, I'm a programmer - you don't need to do all kinds of slow checks to make sure I'm staying where I'm supposed to be, instead I'll be careful about that myself!"
using namespace std;
int main(){
int num = 10; // a) an int is created on stack
int *p = new int; // b) another int is allocated on heap
p = &num; // c) address of int from stack is assigned to p and the pointer
// allocated in b) is leaked: as nothing points to it anymore,
// it can't be deleted
cout << *p << endl;
delete p; // d) deleting a pointer that was not dynamically allocated
// and is pointing to stack.
cout << num << endl;
return 0;
}

Behaviour of reference(&) data member pointing to stack variable

I have come across a sample source code regarding use reference data member and i am confused about output. Here is sample code.
class Test {
private:
int &t;
public:
Test (int y):t(y) { }
int getT() { return t; }
};
int main() {
int x = 20;
Test t1(x);
cout << t1.getT() << "\n"; // Prints 20 as output. however y has already been destroyed but still prints 20.
x = 30;
cout << t1.getT() << endl; // Prints Garbage as output Why ? Ideally both steps should be Garbage.
return 0;
}
And to add for more confusion here is one more piece of code for same class
int main() {
int x = 20;
int z = 60;
Test t1(x);
Test t2(z);
cout<<t1.getT()<<"\n"; // Prints 60! WHY? Should print garbage
cout<<t2.getT() << "\n"; // Prints Garbage
cout<<t1.getT() << endl; // Prints Same Garbage value as previous expression
return 0;
}
x is passed by value using a temporary, so t is a reference to that temporary, not x. That temporary will be destroyed after constructor returns. Your code has undefined behavior. anything can come up as output. Your problem can be solved by passing a reference to x like
Test (int& y):t(y);
but this is not a good idea. There can be cases where x goes out of scope but the Test object is still used , then the same problem will appear.
Your constructor:
Test (int y):t(y) { }
sets t to be a reference to y, the local (temporary) variable on the stack, and not the variable in the calling function. When you change the variable value in the calling function it does not change anything in the object you created.
The fact that the reference is to a temporary variable that is lost at the end of the life of the constructor means that getT() returns an undefined value.
Every call to int getT() accesses the memory address for y. That memory address was released from the stack at the end of the constructor, so it points to memory that is not on the stack or the heap and so may be reused at any time. The time of reuse is not defined and depends on other operations established by the compiler and dependency libraries. The return value of int getT() therefor depends on other elements on your OS that affect memory, the compiler type and version, and the OS amongst other things.
Now i got it. Yes it is undefined but to answer my question why it is printing 20 or 60 before printing garbage? Actually answer is that 20 and 60 both values are garbage and ideally both getT function calls should print Garbage but it doesn't.Because there is no other instruction between Test t2(z);
cout<<t1.getT()<<"\n";
but for next statement \n works as a instruction and meanwhile stack clears the value.

Returning a pointer in a good way

Is this code is completely valid? Will returning a pointer here will not throw us to undefined behavior?
#include <iostream>
using namespace std;
int* lab(int* i) {
int k=9;
i=&k;
return i;
}
int main(void) {
int* i=0;
cout << *lab(i) << endl;
return 0;
}
EDIT: how valid code can look like?
No sir. That is not valid. You can't return a pointer to a local variable. Once lab() exits k does not exist and dereferencing a pointer to it causes undefined behavior.
Think about where k is stored. Automatic variables that you take the address of are stored on the stack. The stack grows when functions are entered and shrinks when they exit. When lab() returns the stack space that was allocated to k is reclaimed and can be reused by the runtime, possibly for other local variables in some other functions.
There are a couple of ways to fix this. The easiest is to have the caller provide a location to store the value in rather than having lab() try to find space. This eliminates the problem of k being deallocated when lab() returns.
int* lab(int* i) {
*i = 9;
return i;
}
int main(void) {
int k;
cout << *lab(&k) << endl;
return 0;
}
Another way is to declare k as static. Static variables are stored in permanent storage somewhere, not on the stack, so their addresses remain valid throughout the lifetime of the program.
int* lab() {
static int k=9;
return &k;
}
And yet another way is to allocate memory on the heap using new.
int* lab() {
int* i = new int;
*i = 9;
return i;
}
int main(void) {
int* i = lab();
cout << *i << endl;
delete i;
return 0;
}
int k will be deleted when the function returns. Hence i will point to an unallocated part of memory. ERROR
No it is not valid. lab returns a pointer to a variable local variable. That pointer is not valid once lab exists. Access it is undefined behavior.

Returning pointer to local function variable [duplicate]

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?
I know that I should not return pointers to local function variables (local stack variables) because when the function return, the variables will be invalid and the stack will be cleaned up unless I made these variables static or allocated them on heap.
The following code demonstrates that:
const char* v1() {
return "ABC";
}
const char* v2() {
string s = "DEF";
return s.c_str();
}
const char* v3() {
static string s = "JHI";
return s.c_str();
}
cout << v1() << endl; // Output: ABC
cout << v2() << endl; // Output: garbage (♀ ╠╠╠╠╠╠╠╠)
cout << v3() << endl; // Output: JHI
However, I returned pointer to a primitive local function variable and I was able to get its value although it is not static, as the following code shows:
int i1() {
int i = 5;
return i;
}
int* i2() {
int i = 6;
return &i;
}
int* i3() {
static int i = 7;
return &i;
}
cout << i1() << endl; // Output: 5
cout << *i2() << endl; // Output: 6 !!
cout << *i3() << endl; // Output: 7
The compiler only gives me warning that I am returning address of local variable or temporary (Visual C++ 2008). Is this behaviour common to all compilers and how the compiler allows me to use pointer to a local function variable to access the value it points to although the variable is invalidated when the function return?
you return an address. Returning an address is valid - always. But in your case, you also dereference it. This is undefined behavior. Theoretically, for undefined behavior, anything can happen. The compiler is even allowed to embed code to format your hard-disc. Practically it will dereference the address without any checks. If it is still accessible, it'll return the value at that address otherwise it'll cause an access violation.
Your address is on the stack, so it is always accessible. Depending on the calls you made in between, the value might still be there or not. So in simple cases, you get the value back, in more complicated cases you won't. It may even work sometimes and sometimes it does not.
For more information, you should read some information on how function calls are made in assembler to understand what the compiler is doing there on the stack (placing parameters, return address, placing local variables, stack cleanup on return, calling conventions).
it can be removed from the stack because it is local but the value will remain until another overwirte it.
it is c++ unsafe language u can do much strange things