c - Why is the stack size different in different runs of the same program? -
consider following program. takes argument command line , unrolls recursive function limit.
#include <stdio.h> #include <stdlib.h> int rec(int x, int limit) { if (x == limit) { return limit; } int r = rec(x + 1, limit); return r - 1; } int main(int arc, char* argv[]) { int result, limit; limit = atoi(argv[1]); printf("stack: %p\n", &result); result = rec(0, limit); printf("%d\n", result); }
if compile expect run out of stack fixed input argument limit. else happens.
dejan@raven:~/test/stack$ gcc stack.c dejan@raven:~/test/stack$ ./a.out 174580 stack: 0x7fff42fd58f0 segmentation fault (core dumped) dejan@raven:~/test/stack$ ./a.out 174580 stack: 0x7ffdd2dd8b20 0
in 2 different runs, stack size seems different. doesn't seem compiler issue same thing happens clang, , disassembly doesn't involve strange.
why stack sizes on different runs different?
i have added /proc/self/maps
parser program (same approach @andrewhenle advises, on start of program, , not invoke pmap
):
char* get_stack_bounds() { file* maps = fopen("/proc/self/maps", "r"); static char line[256]; while(!feof(maps)) { fgets(line, 255, maps); if(strstr(line, "[stack]")) { char* space = strchr(line, ' '); *space = '\0'; fclose(maps); return line; } } fclose(maps); return null; } unsigned long get_stack_right() { char* bounds = get_stack_bounds(); bounds = strchr(bounds, '-') + 1; return strtol(bounds, null, 16); }
and dump information in beginning of main()
:
printf("&result: %p delta: %ld\n", &result, get_stack_right() - ((unsigned long) &result));
here results:
> ./a.out 104747 &result: 0x7fff3347c7f8 delta: 6152 0 > ./a.out 174580 &result: 0x7fffe43c9b38 delta: 5320 0 > ./a.out 174580 &result: 0x7fff26ad2b28 delta: 9432 segmentation fault (core dumped) > ./a.out 174580 &result: 0x7fff145aa5a8 delta: 6744 0 > ./a.out 174580 &result: 0x7fff74fff0b8 delta: 12104 segmentation fault (core dumped)
i think correlation between delta
(which difference between result
address , base address of stack) , segmentation fault obvious.
you should note main()
not first function runs in program, actual entry point _start()
crt1.o (or whatever), initial stack size can differ.
actual problem address space layout randomization . here comment fs/binfmt_elf_fdpic.c
regarding usage:
/* in cases (e.g. hyper-threading), want avoid l1 evictions * processes running on same package. 1 thing can * shuffle initial stack them, give architecture * opportunity here. */ sp = arch_align_stack(bprm->p);
here implementation of arch_align_stack()
on x86:
unsigned long arch_align_stack(unsigned long sp) { if (!(current->personality & addr_no_randomize) && randomize_va_space) sp -= get_random_int() % 8192; return sp & ~0xf; }