Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
#include <stdio.h>
typedef struct {
int x,y;
} point;
point* create_point(int x,int y) {
point p={x,y};
point* ptr = &p;
return ptr;
}
int main() {
point* p1 = create_point(1,2);
point* p2 = create_point(6,7);
printf("%d, %d, ", p1->x, p1->y);
printf("%d, %d \n", p2->x, p2->y);
return 0;
}
When I compile with repl.it I get 6,7,0,0 as output but when I run the same program with sublime text editor, I get a different output : 6,7,6,7. Does anyone know why? and which output is the correct output? Any help is appreciated, thank you.
Generally, when you have a "factory" function that creates and returns a pointer to an object, the object should be allocated on the heap with malloc(), like so:
int *factory(){
int *p;
p = malloc(sizeof(whatever));
return p;
}
In C, function returns are by value. In this case, while p is a local, stack-allocated variable, it is a pointer and its value (which is what is passed back to the caller) will be the address of the heap-allocated object returned by malloc() so it is a meaningful value outside the scope of the function.
In your function create_point(), you're returning a pointer, but because p is a local (automatic) variable, it is allocated on the stack and so the pointer to it that you're returning will refer to an address that had been in create_point()'s stack frame. Depending on how a given compiler orders automatic variables on the stack (and what order you access them in) as well as other information it needs to place there per the ABI, it's possible that you might have gotten lucky and received the results you expected if you only called create_point() once, and you would have never detected this error. But the second call's stack frame is likely in the same position as or overlaps with the position of the first call's stack frame on the process's stack, meaning that some or all of the contents left over from the first call (since a function call's stack frame generally isn't cleared once the function returns, the old values will still be there until those memory locations are overwritten) would get clobbered by both the second call to create_point() as well as the subsequent calls to printf().
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
typedef struct{
int x;
int y;
} Coordinate_T;
Coordinate_T *p;
p = (Coordinate_T *)malloc(sizeof(Coordinate_T));
p->x = 100;
p->y = 200;
free(p);
exit(0);
I'm trying to get the hang of pointers but it is really confusing when they are used like this. I got this code from a textbook and I'm supposed to find what's wrong with this code
Woo, it's been a long time since I dealt with C pointers, but let me see if I can help.
Coordinate_T *p;
declares a pointer to a Coordinate_T struct. We don't have any memory available yet, we just have a pointer to... nothing.
p = (Coordinate_T *)malloc(sizeof(Coordinate_T))
actually allocates the memory for us. Now p points to something useful where we can store values. "malloc" is shorthand for "memory allocation." It requires a size - how much memory do you need? "sizeof(Coordinate_T)" is an easy way to say "the size of this struct that I want to point to. Finally, the type cast "(Coordinate_T *)" tells the compiler "treat this like a Coordinate_T pointer".
p->x = 100;
p->y = 200;
Sets the x value of our newly-allocated struct to 100, and the y value to 200. The arrow notation (->) says "p is a pointer; inside the memory it points to, set..."
free(p)
frees the memory you just allocated with malloc(). This means we're done with it, the operating system can use that memory for something else. If you don't free memory when you're done with it, that's a "memory leak" - it's still marked as being in-use, and the operating system can't re-use it. In a long-running program, the leaked memory can build up and build up, and eventually the operating system kills the running program when no more memory is available.
exit(0);
just kills the program, and returns the value zero, which is the traditional value that means "Everything is fine." If a program returns any other value, that means some error occurred.
tl;dr: This program doesn't do much. It sets a couple values, then throws away the memory it used, and exits. It would be more interesting to include a printf() statement to echo those values back to you, but I'll leave that to you. ;-)
Consider the following code.
#include<stdio.h>
int *abc(); // this function returns a pointer of type int
int main()
{
int *ptr;
ptr = abc();
printf("%d", *ptr);
return 0;
}
int *abc()
{
int i = 45500, *p;
p = &i;
return p;
}
Output:
45500
I know according to link this type of behavior is undefined. But why i am getting correct value everytime i run the program.
Every time you call abc it "marks" a region at the top of the stack as the place where it will write all of its local variables. It does that by moving the pointer that indicates where the top of stack is. That region is called the stack frame. When the function returns, it indicates that it does not want to use that region anymore by moving the stack pointer to where it was originally. As a result, if you call other functions afterwards, they will reuse that region of the stack for their own purposes. But in your case, you haven't called any other functions yet. So that region of the stack is left in the same state.
All the above explain the behavior of your code. It is not necessary that all C compilers implement functions that way and therefore you should not rely on that behavior.
Well, undefined behavior is, undefined. You can never rely on UB (or on an output of a program invoking UB).
Maybe, just maybe in your environment and for your code, the memory location allocated for the local variable is not reclaimed by the OS and still accessible, but there's no guarantee that it will have the same behavior for any other platform.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Not able to understand the code. The correction option is d but i m not understanding how it comes out to be d.
#include <stdio.h>
int *m();
void main()
{
int k = m();
printf("%d",k);
}
int *m()
{
int a[2]={5,8};
return a;
}
options are:
a) 5
b) 8
c) nothing
d) varies
The compiler is showing following warnings:
1)warning: return makes integer from pointer without a cast
return a;
2)warning: function returns address of local variable [-Wreturn-local-addr]
and I am not able to interprete both.
It's no surprise you have trouble understanding that code, because it is very poorly written.
The main problem is that the a array in the m() function ceases to exist when m returns, so any pointer to that array is no longer valid1, and attempting to read or write anything through an invalid pointer leads to undefined behavior.
"Undefined behavior" simply means that the code is erroneous, but the compiler isn't required to handle it in any specific way. Your program may crash outright, it may be put into a bad state that doesn't manifest until later, it may corrupt data, or it may appear to run without any issues.
So yes, the result may vary, but that's understating the case by a lot. The right answer is "E) The behavior is undefined".
But there are other problems in the code. m() returns a pointer to int, but the program assigns the result to a plain int, hence the first warning. Whoever wrote that code either doesn't understand types, or assumes that pointer values and int values are interchangeable (not necessarily a valid assumption).
Either that, or the original code is actually
int k = *m();
And, finally, main() returns int, not void, as in:
int main( void ) // or int main( int argc, char **argv ) if your program takes
// command line arguments.
Obviously, the memory location that a occupied still exists, but after m() exits, that memory may be overwritten or used by something else.
The first warning (MSVC compiler)
int differs in levels of indirection from int *
is because you are trying to supply a pointer for int k in main, which is not a pointer.
The second warning
returning address of local variable or temporary: a
is because a function's local variable goes out of life after the function returns.
I would suggest you use malloc in your function to obtain memory for the array, and return that to a pointer variable in main. Having done that, you can print the first element. But I won't post the code for that, since you "copied the code as it is from the website".
Thanks for making updates to your question, I think I understand what's going on, now. My C is a bit rusty, but here goes:
The method m returns an int* (pointer/address to int)
When m is called, it creates a as a local array on the stack. Then, it tries to return the address for a.
When m is completed and returns control back to main, the memory on allocated by m on the stack goes out of scope. a is among the items on that stack that has gone out of scope.
Because the data at the address a is out of scope, it's considered "undefined behavior" to access/dereference it, which is what main (almost) does with the printf call. This is what 2)warning: function returns address of local variable [-Wreturn-local-addr] is warning you of.
The answer, "varies", would've been more accurate as "undefined behavior".
A separate issue highlighted by the error:
1)warning: return makes integer from pointer without a cast
Is that m() returns a pointer to an int, but it's being assigned to int k.
The reason that the behavior "varies" (D) is because m() is returning a, which is a memory address. Each time you run your program, that address could change because your OS can load the program anywhere in memory that it wants.
Now if your program were doing what I think you actually want it to - to print the contents at the memory address returned by m() - that would be:
int *k = m();
printf("%d\n", *k);
But this would still result in behavior "varies" though, for the local variable issue described by the other answers.
Your compiler warning: 2)warning: function returns address of local variable [-Wreturn-local-addr] is occurring because m() is returning a, which is a local variable. Look up "local variables" on the googles for more information. This is useful: Difference between static, auto, global and local variable in the context of c and c++
Your compiler warning: 1)warning: return makes integer from pointer without a cast is because you're storing the return value of m(), which is of type int* into variable k, which is of type int. You need to make these the same type in order to get rid of the compiler warning. Look up "C pointers" on the googles for more information. This tutorial seems reasonable: http://www.programiz.com/c-programming/c-pointers
Consider the following code.
#include<stdio.h>
int *abc(); // this function returns a pointer of type int
int main()
{
int *ptr;
ptr = abc();
printf("%d", *ptr);
return 0;
}
int *abc()
{
int i = 45500, *p;
p = &i;
return p;
}
Output:
45500
I know according to link this type of behavior is undefined. But why i am getting correct value everytime i run the program.
Every time you call abc it "marks" a region at the top of the stack as the place where it will write all of its local variables. It does that by moving the pointer that indicates where the top of stack is. That region is called the stack frame. When the function returns, it indicates that it does not want to use that region anymore by moving the stack pointer to where it was originally. As a result, if you call other functions afterwards, they will reuse that region of the stack for their own purposes. But in your case, you haven't called any other functions yet. So that region of the stack is left in the same state.
All the above explain the behavior of your code. It is not necessary that all C compilers implement functions that way and therefore you should not rely on that behavior.
Well, undefined behavior is, undefined. You can never rely on UB (or on an output of a program invoking UB).
Maybe, just maybe in your environment and for your code, the memory location allocated for the local variable is not reclaimed by the OS and still accessible, but there's no guarantee that it will have the same behavior for any other platform.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Returning the address of local or temporary variable
The add function is implemented wrongly. It should return a value instead of a pointer.
Why aren't any errors when ans and *ans_ptr are printed and the program even gives correct result? I guess the variable of z is already out of scope and there should be segmentation fault.
#include <stdio.h>
int * add(int x, int y) {
int z = x + y;
int *ans_ptr = &z;
return ans_ptr;
}
int main() {
int ans = *(add(1, 2));
int *ans_ptr = add(1, 2);
printf("%d\n", *ans_ptr);
printf("%d\n", ans);
return 0;
}
The reason it 'works' is because you got lucky. Returning a pointer to a local variable is Undefined Behaviour!! You should NOT do it.
int * add(int x, int y) {
int z = x + y; //z is a local variable in this stack frame
int *ans_ptr = &z; // ans_ptr points to z
return ans_ptr;
}
// at return of function, z is destroyed, so what does ans_ptr point to? No one knows. UB results
Because C has no garbage collection, when the "z" variable goes out of scope, nothing happens to the actual memory. It is simply freed for another variable to overwrite if the compiler pleases.
Since no memory is allocated between calling "add" and printing, the value is still sitting in memory, and you can access it because you have its address. You "got lucky."
However, as Tony points out, you should NEVER do this. It will work some of the time, but as soon as your program gets more complex, you will start ending up with spurious values.
No. Your question displays a fundamental lack of understanding of how the C memory model works.
The value z is allocated at an address on the stack, in the frame which is created when control enters add(). ans_ptr is then set to this memory address and returned.
The space on the stack will be overwritten by the next function that is called, but remember that C never performs memory clean up unless explicitly told to (eg via a function like calloc()).
This means that the value in the memory location &z (from the just-vacated stack frame) is still intact in the immediately following statement, ie. the printf() statement in main().
You should never ever rely on this behaviour - as soon as you add additional code into the above it will likely break.
The answer is: this program works because you are fortunate, but it will take no time to betray, as the address you return is not reserved to you anymore and any one can use it again. Its like renting the room, making a duplicate key, releasing the room, and after you have released the room at some later time you try to enter it with a duplicate key. In this case if the room is empty and not rented to someone else then you are fortunate, otherwise it can land you in police custody (something bad), and if the lock of the room was changed you get a segfault, so you can't just trust on the duplicate key which you made without acquisition of the room.
The z is a local variable allocated in stack and its scope is as long as the particular call to the function block. You return the address of such a local variable. Once you return from the function, all the addresses local to the block (allocated in the function call stack frame) might be used for another call and be overwritten, therefore you might or might not get what you expect. Which is undefined behavior, and thus such operation is incorrect.
If you are getting correct output, then you are fortunate that the old value held by that memory location is not overwritten, but your program has access to the page in which the address lies, therefore you do not get a segmentation fault error.
A quick test shows, as the OP points out, that neither GCC 4.3 nor MSVC 10 provide any warnings. But the Clang Static Analyzer does:
ccc-analyzer -c foo.c
...
ANALYZE: foo.c add
foo.c:6:5: warning: Address of stack memory associated with local
variable 'z' returned to caller
return ans_ptr;
^ ~~~~~~~