Understanding Stack Frames in C
Asked Answered
D

2

6

I am trying to understand the stack frame in C, so I wrote a simple C code to analyze the stack frame.

  • First of all the fun1() returns an address of a local variable which is initialized to 10 to ptr which leads to a warning but that's ok... If I print the value of *ptr now it prints 10, even that's fine...

  • Next fun2() returns an address of a local variable which is not even initialized and if I try to print the value of *ptr now it prints 10 no matter if i'm returning an address of a or b...

  • To understand what is actually happening here I made use of gdb. Using gdb, I started step by step debugging and when I reached the line "return &a" in fun2(), I tried to print address of b, print &b but it printed Can't take address of "b" which isn't an lvalue.

I don't understand when I try to print the address of a, print &a it prints absolutely fine then why not address of b. * Why isn't b an lvalue when a is?

# include <stdio.h>

int * fun1() {
    int a = 10; 
    return &a; 
}

int * fun2()
{
    int a;
    int b;
    return &a;           // return &b;
}

int main ()  
{
    int *ptr;
    ptr = fun1();
    ptr = fun2();
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}
Doited answered 25/4, 2014 at 5:27 Comment(4)
https://mcmap.net/q/537722/-segmentation-fault-when-writing-to-a-string-duplicateSeparate
You're invoking undefined behavior. There is no guarantee that the results will make any sort of sense or do what you'd expect from the stack layout. The standard hyperbole is that the program is allowed to make demons fly out your nose.Healy
You're lucky that printing *ptr prints 10; it is certainly not guaranteed to do so (you're invoking undefined behaviour). But you really should show all the code. In the code, the compiler probably dropped b as an unused variable, so it doesn't have a location, hence you can't take its address. Use b in the code, somehow, and you'll be able to print it. And please, don't report "something like"; be precise, and report exactly what the debugger says.Methoxychlor
If you are asking for docs about the "stack frame" then this is an ABI-related request, nothing really related to any programming language in particular, you should document yourself about the ABI adopted/offered by your CPU/architecture/OS/implementation. If your problem is understanding how C works, than the focus is on a totally different topic.Scuppernong
O
3

The compiler is optimizing away some code in fun2.

If you return &a, it is optimizing away int b;. If you return &b, it is optimizing away int a;. If you add some dummy computation, you will see that the addresses of returned values will be different.

int * fun2()
{
    int a;
    int b;
    int* p = &a;
    p = &b;
    return p;
}

Change main to print the returned values of fun1 and fun2.

int main ()  
{
    int *ptr;
    ptr = fun1();
    printf ("ptr = %p, fun1() called...\n", ptr);
    ptr = fun2();
    printf ("ptr = %p, fun2() called...\n", ptr);
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}

When I run this code, I get the following sample output:

ptr = 0x7ffff98c70ec, fun1() called...
ptr = 0x7ffff98c70e4, fun2() called...
*ptr = 32749, fun2() called...
Orellana answered 25/4, 2014 at 5:40 Comment(1)
Ya that's true if I initialize b, it returns a garbage but the same should be true if I compile with -O0 level of optimization. But when I compile it with -O0 level of optimization the result is same again i.e 10Doited
B
0

It compiles for me just fine when returning the address to b. But you aren't supposed to return the address of a local variable. Check out this link.

Beyrouth answered 25/4, 2014 at 5:36 Comment(1)
Ya that's true but my aim here is not to accomplish anything from this code but to understand how the stack variable's address being used in one function can be re-used in another function... Thanks for the help...Doited

© 2022 - 2024 — McMap. All rights reserved.