1

I have this function I coded who's purpose is to print the entire stack frame of the function it is called in:

#include <stdio.h>
#define FRAME_TYPE_SIZE sizeof(void *)

void view_stack_frame(){
    void *start = __builtin_frame_address(1);
    void *stop = __builtin_frame_address(0);

    printf("\n[View Stack Frame] %p\n", &view_stack_frame);
    printf("Address of stack frame: %p\n",stop);
    printf("Address of caller's frame: %p\n",start);

        printf("\nADDRESS\t\t\tVALUE\n");

        while(start>stop){
            start -= FRAME_TYPE_SIZE;
            long *p = (long *) start;
            printf("[%p] \t%ld\n",start,*p);
        }
}

And I am using this code to call it:

#include "stackBACKUP.h"

void caller3(){
    FTYPE var1 = 1000;
    FTYPE var2 = 2000;
    FTYPE var3 = 3000;
    FTYPE var4 = 4000;
    FTYPE var5 = 5000;
    FTYPE var6 = 6000;
    FTYPE var7 = 7000;
    view_stack_frame();
}

void caller2(){
    FTYPE var1 = 1000;
    FTYPE var2 = 2000;
    FTYPE var3 = 3000;
    FTYPE var4 = 4000;
    FTYPE var5 = 5000;
    view_stack_frame();
}

void caller(){
    FTYPE var1 = 1000;
    FTYPE var2 = 2000;
    FTYPE var3 = 3000;
    FTYPE var4 = 4000;
    FTYPE var5 = 5000;
    FTYPE var6 = 6000;
    view_stack_frame();
}

int main(void){
    caller();
    caller2();
    caller3();
}

However, when I run the code, this is what I end up getting as output:

[View Stack Frame] 0x55fd8fb3267a
Address of stack frame: 0x7ffd03486770
Address of caller's frame: 0x7ffd034867b0

ADDRESS         VALUE
[0x7ffd034867a8]    6000
[0x7ffd034867a0]    5000
[0x7ffd03486798]    4000
[0x7ffd03486790]    3000
[0x7ffd03486788]    2000
[0x7ffd03486780]    1000
[0x7ffd03486778]    94547525969897
[0x7ffd03486770]    140724658530224

[View Stack Frame] 0x55fd8fb3267a
Address of stack frame: 0x7ffd03486770
Address of caller's frame: 0x7ffd034867b0

ADDRESS         VALUE
[0x7ffd034867a8]    5000
[0x7ffd034867a0]    4000
[0x7ffd03486798]    3000
[0x7ffd03486790]    2000
[0x7ffd03486788]    1000
[0x7ffd03486780]    1000
[0x7ffd03486778]    94547525969828
[0x7ffd03486770]    140724658530224

[View Stack Frame] 0x55fd8fb3267a
Address of stack frame: 0x7ffd03486760
Address of caller's frame: 0x7ffd034867b0

ADDRESS         VALUE
[0x7ffd034867a8]    7000
[0x7ffd034867a0]    6000
[0x7ffd03486798]    5000
[0x7ffd03486790]    4000
[0x7ffd03486788]    3000
[0x7ffd03486780]    2000
[0x7ffd03486778]    1000
[0x7ffd03486770]    140724658530224
[0x7ffd03486768]    94547525969767
[0x7ffd03486760]    140724658530224

I understand what the last 2 values are, when converted to hex, the second to last is slightly before the address of the stack frame, and the last one is the address of the caller's frame. However,I can see some problems here.

The method with 5 variables ends up having an additional entry right after the LAST variable, which is the same as it. The method with 7 variables ends up having an additional entry after the last variable, but this time that entry is the same as the ADDRESS OF THE FUNCTION.

From what I can tell, the stack frame looks like this: [ variables ] [ addresses of functions ] But for the method with 5 and 7 variables, it looks like this: [ variables ] [ last variable ] [ addresses ] [ variables ] [ address of function ] [ addresses ].

I did a lot of research about how stack frames work in C, but I don't know what is going on. I also don't know assembly, so I cannot really dissassemble this code and know how it works.

Can someone tell me why all these anomalys happen, and how to avoid them?

ENBYSS
  • 819
  • 1
  • 10
  • 22
  • It seems that some garbage values of the previous call have remained. Changing the order of calls (`caller2` -> `caller` -> `caller3`) showed a different result. – Simon Woo Nov 20 '17 at 20:09
  • No reason. There might be requirements that the stack frame can only have certain sizes to be properly aligned, so parts of it might be unused. Displaying unused parts of the stack frame can produce absolutely anything. Why are you interested in the memory that your program is not using? – Bo Persson Nov 20 '17 at 22:40
  • @SimonWoo, the repeated 1000 in caller 2 becomes 1 when I execute it first... as for the other values, I believe they change because they are addresses – ENBYSS Nov 21 '17 at 13:30
  • @BoPersson the thing is, I do not know how to NOT display unused memory. I can't really find a way to discern actual variables/parameters from memory locations... – ENBYSS Nov 21 '17 at 13:32
  • 1
    You are not really supposed to display stack frames, you are supposed to use the variables declared in the function. If you do, you just get the bytes actually used. Because of reasons, like alignment rules, a stack frame *might* have to be of a certain size - like 32 or 64 bytes, but not 11 or 42. So if you use less than 32 bytes, the frame will still allocate 32 bytes and just not use some of them. If you display the unused bytes, they still contain bits that form a value when displayed. But as these bytes are not used by the program, it really doesn't matter. And you shouldn't be concerned. – Bo Persson Nov 21 '17 at 23:15

0 Answers0