This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 4 years ago.
I made a function to convert an array of ints (a zipcode) into a cstring. If I call the function, the return is gibberish, but if I cout the returned variable inside the function it's exactly as expected.
const char* print_zip(const int* zip) {
char output[6];
char* ctemp = output;
const int *itemp = zip;
for (int i = 0; i < 5; i++) {
*ctemp = *itemp + 48; // convert to char numbers.
itemp++; // iterate using pointers rather than []
ctemp++; // per assignment specifications
}
*ctemp = '\0';
std::cout << output << std::endl; // (debug only) as expected
return output; // cout << print_zip(); not as expected
}
When you cout the return variable inside the function, it should be expected to return the value wanted. This is because when you create a local variable inside a function it resides in that function's stack frame. Thus, when STILL inside the function, the scope is still set to see that variable.
On the contrary, when the pointer to the local variable is returned, the stack frame no longer exists, basically meaning the pointed to object could or could not be complete junk.
In order to return a variable that will be constant within or out of the stack frame, you would need to pass it by reference, which is usually done by making a copy of object your trying to return, then returning that copy.
Related
This question already has answers here:
What happens when I call a function without assigning its returned value to a variable? [duplicate]
(4 answers)
Closed 5 years ago.
In the program, it has:
EnergyFunctional* ef;
ef->insertFrame(fh, &Hcalib);
The function is defined as follows:
EFFrame* EnergyFunctional::insertFrame(FrameHessian* fh, CalibHessian* Hcalib)
{
EFFrame* eff = new EFFrame(fh);
eff->idx = frames.size();
frames.push_back(eff);
nFrames++;
fh->efFrame = eff;
assert(HM.cols() == 8*nFrames+CPARS-8); /// CPARS = 4
bM.conservativeResize(8*nFrames+CPARS);
HM.conservativeResize(8*nFrames+CPARS,8*nFrames+CPARS);
bM.tail<8>().setZero();
HM.rightCols<8>().setZero();
HM.bottomRows<8>().setZero();
EFIndicesValid = false;
EFAdjointsValid=false;
EFDeltaValid=false;
setAdjointsF(Hcalib);
makeIDX();
for(EFFrame* fh2 : frames)
{
connectivityMap[(((uint64_t)eff->frameID) << 32) + ((uint64_t)fh2->frameID)] = Eigen::Vector2i(0,0); /// move left 32 bits
if(fh2 != eff)
connectivityMap[(((uint64_t)fh2->frameID) << 32) + ((uint64_t)eff->frameID)] = Eigen::Vector2i(0,0); /// index is totally 64 bits, front 32 bits for each frame, rear 32 bits for current frame
}
return eff;
}
It seems like the return type should be void so that it can be consistent with last sentence...
I also checked if there is other same name "inserFrame" functions, but there is not.
This program can be compiled successfully, but why can it be no problem?
The return type specified by the function is EFFrame*, which is a pointer to an EFFrame object. The value being returned by the function is eff, which is a EFFrame* type pointer as well. So there shouldn't be any confusion.
You would only use a void return type in the function declaration if you are not returning a value. However, as shown in the last line, this function is clearly trying to return a pointer to a EFFrame object.
However, even in functions that have a clearly defined return type, it may not be necessary to use that value. Hence it is technically legal to just call the function and not store the return value into a variable. Hence, even though ef->insertFrame(fh, &Hcalib); is calling the function and returning a EFFrame* pointer, it just isn't being stored.
This question already has answers here:
const_cast doesn't work c++? [duplicate]
(3 answers)
Closed 6 years ago.
After const_cast, the value does not change in the main function. But changes when calling an external function, still prints the old value in the main (where const int is initialized first).
int main() {
const int i = 5;
int* p = const_cast<int*>(&i);
*p = 22;
std::cout<<i;
return 0;
}
Output is 5, why? The watch-window shows value of i = 22:
So why does it print 5 ? The output differs if I call an external function:
void ChangeValue(const int i) {
int* p = const_cast<int*>(&i);
*p = 22;
std::cout<<i; //Here the value changes to 22
}
int main() {
const int i = 5;
ChangeValue(i); //Value changes to 22 in the ChangeValue function
std::cout<<i // It again prints 5.
}
Why is the value not changed even if the value changes after calling the ChangeValue function?
I get the same output on a Linux Platform. Could someone please add clarity to my confusion?
Trying to modify a constant value leads to undefined behavior, just don't do it.
As for why it doesn't change, the compiler sees that it is a compile-time constant and may store it in a read-only segment.
For the second program, the variable i can't be stored in a read-only segment, it's stored on the stack like any other local variable. However, since you marked i as constant attempting to modify it is still undefined behavior.
The reason the main program prints the old value, is because you pass the variable by value meaning it gets copied into the local variable i in the ChangeValue function. If the variable wasn't a constant in the main or the ChangeValue function, the value of i in the main function would still not change.
If you change the ChangeValue function to take its argument by reference, you might get the same behavior as the first program.
This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 8 years ago.
Suppose I have the following functions:
char* allocateMemory()
{
char str[20] = "Hello world.";
return str;
}
int* another()
{
int x = 5;
return &x;
}
int _tmain(int argc, _TCHAR* argv[])
{
char* pString = allocateMemory();
printf("%s\n", pString);
int* blah = another();
printf("%d %d \n", blah, *blah);
return 0;
}
The first printf prints random values, because str IS LOCAL SCOPE.
The second printf prints the proper values, with blah = address of blah, *blah = 5
Why is it that local scope only affects allocateMemory which deals with arrays, but not integer?
Why does the first printf (returning char* ) prints random values and is affected by local scope, but not the second one (returning int* )?
Both ways of accessing the local variables of a method which goes out of scope is Undefined Behavior. These are some valid ways:
char* allocateMemory()
{
char* str= malloc(sizeof(char) * 20); //assuming C
strcpy(str, "Hello World.");
return str; //Valid
}
const char* allocateMemory()
{
return "Hello world."; //Valid Hello World is in read only location
}
int* another()
{
int *x = malloc(sizeof(int)); //assuming C
*x = 5;
return x; //Valid
}
char str[20] = "Hello world.";
str is local to function allocateMemory() and is no more valid once you exit the function and hence accessing it out of its scope if undefined behavior.
int x = 5;
The same applies here also.
You can have your data on heap and return the pointer to it is valid.
char *allocatememory()
{
char *p = malloc(20); /* Now the memory allocated is on heap and it is accessible even after the exit of this function */
return p;
}
Change the first function to:
char* allocateMemory()
{
static char str[20] = "Hello world.";
return str;
}
and see the difference.
And now explanation:
When you return address of local data (variable or array, does not matter - it is AUTOMATIC variables) you have a risk to lose data or make a mess in the memory. It was just a good luck that integer data was correct after the second function call. But if you return address of STATIC variables - no mistakes. Also you can allocate memory from HEAP for data and return address.
These are both, of course, UB, as the other answerers said. They also gave some good ways to do what you want to do in a proper fashion. But you were asking why does this actually happen in your case. To understand it, you need to understand what happens in the stack when you call a function. I'll try to provide a really simplified explanation.
When a function is called, a new stack frame is created on top of the stack. All the data in the function is put onto the stack frame. So, for the function
char* allocateMemory()
{
char str[20] = "Hello world.";
return str;
}
The stack frame for allocateMemory will contain, besides some other stuff, the 20 elements of the string (char array) str.
For this function:
int* another()
{
int x = 5;
return &x;
}
The stack frame for another will contain the contents of the variable x.
When a function returns, the stack pointer, which marks the top of the stack, drops all the way down to where it was before a function invocation. However, the memory is still there on the stack, it doesn't get erased - it is a costy and pointless process. However, there is no longer anything protecting this memory from being overwritten by something: it has been marked "unneeded".
Now, what's the difference between your calls to printf? Well, when you call printf, it gets its own stack frame. It overwrites what was left of the previous called function's stack frame.
In the first case, you just pass pString to printf. Then printf overwrites the memory that once was the stack frame of allocateMemory, and the memory that was once str gets covered with stuff printf needs to work with string output, like iteration variables. Then it proceeds to try and get memory pointed to by the pointer you passed to it, pString... But it has just overwritten this memory, so it outputs what looks like garbage to you.
In the second case, you first got the value of the pointer blah, which resides in your local scope. Then you dereferenced it with *blah. Now comes the fun part: you've done the dereferencing before you've called another function which could overwrite the contents of the old stack frame. Which means the memory that was once the variable x in the function another is sort of still there, and by dereferencing the pointer blah, you get the value of x. And then you pass it to printf, but now, it doesn't matter that printf will overwrite another's stack frame: the values you passed to it are now sort of "safe". That's why the second call to printf outputs the values you expect.
I've heard of people who dislike using the heap so much that they use this "trick" in the following way: they form a stack array in a function and return a pointer to it, then, after the function returns, they copy its contents to an array in the caller's scope before calling any other function, and then proceed to use it. Never do this, for the sake of all the people who may read your code.
This question already has answers here:
Char * (pointer) function
(4 answers)
When I change a parameter inside a function, does it change for the caller, too?
(4 answers)
Closed 8 years ago.
I have the following very simple program.
int modify(char * v){
v = "123" ;
return 0;
}
int main (int argc, char** argv){
char *test = new char[10];
modify(test);
std::cout << test;
return 0;
}
I know I can just print out "123", but I deliberately wrote it that way to learn about how pointers work. However, "123" is not printed. How should I correctly pass the pointer?
You have to remember that in C++ arguments are by default passed by value, meaning that in the function you have copies., and modifying a copy will not change the original.
If you want to change the pointer to point to something else you need to pass it by reference. However, in this case it will cause other problems, as you then loose the original pointer.
So the solution is to either use std::string passed by reference, or by using strcpy top copy into the destination memory area (but if you use strcpy you have to take care to not write beyond the allocated memory).
Try this inside modify strcpy(v, "123")
There are several problems with your code.
Your modify() function actually changes nothing:
int modify(char * v) {
v = "123"; // overwrites the parameter value copy on the stack
// with a char[] literal pointer
return 0;
}
You need to copy from the literal to the pointer:
int modify(char* v) {
strcpy(v,"123");
return 0;
}
You do not free the allocated memory, which may lead to memory leaks in other situations
int main (int argc, char** argv){
char *test = new char[10];
modify(test);
std::cout << test;
delete [] char; // <<< Note
return 0;
}
As Joachim Pileborg already mentioned the most approriate solution for c++ would be to use a std::string instead of char*.
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