0

/*

learning from all the post - please correct me if i am wrong..

now it makes sense- if i remember it right, the stack is a fixed memory segment- allocated on program start up... while the virtual memory can be sized/resized programmatically using malloc, realloc, free... the struct pointer array -

long size = 10000000; struct foo *bar[size];

should have been allocated from heap - using malloc()... instead of just a fixed size stack (program text)

*/

This one SIGSEV's:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    
    struct foo {
        int x;
        char s[5];
    };

    long size = 10000000;
    struct foo *bar[size];

    long i = 0;
    while (i < size) {
        printf("%ld \n", i);
        i++;
    }
}

This one works - commenting out the struct foo pointer array:

#include <stdio.h>
#include <stdlib.h>
    
int main(void) {

    struct foo {
        int x;
        char s[5];
    };

    long size = 10000000;
    //struct foo *bar[size];

    long i = 0;
    while (i < size) {
        printf("%ld \n", i);
        i++;
    }
}

This one works - commenting our the while loop:

#include <stdio.h>
#include <stdlib.h>
    
int main(void) {

    struct foo {
        int x;
        char s[5];
    };

    long size = 10000000;
    struct foo *bar[size];

    long i = 0;
    
    while (i < size) {
        //printf("%ld \n", i);
        i++;
    }
}

/* what i really am trying to achieve is this... which SIGSEVS - ok thanks for all your replies i really appreciate it...

  • will look int stack overflow and use explore using heap memory-- thanks guys */
int main(void) {

    struct foo {
        int x;
        char s[5];
    };

    long size = 10000000;
    struct foo *bar[size];

    long i = 0;
    while (i < size) {
        bar[i] = (struct foo *) malloc(sizeof(struct foo));
        free(bar[i]);
        i++;
    }
    return EXIT_SUCCESS;
}
Chris
  • 26,361
  • 5
  • 21
  • 42
knostika
  • 23
  • 5
  • 3
    It is likely that your stack is limited to 8 MiB, so when you try to create a local array that is bigger than the limit, you crash. The while loop case is mildly puzzling; the compiler may have optimized everything away. – Jonathan Leffler Mar 19 '14 at 16:09
  • you are right man... should refrain from using such big sized block on the stack - instead with such situations i should use the heap instead... tnx man – knostika Mar 19 '14 at 16:54

3 Answers3

9
long size = 10000000;
struct foo *bar[size];

will create a very big array, which may cause stack overflow, and therefore your program receive the SIGSEV.

You should create this array dynamically:

struct foo *bar = malloc(size * sizeof(struct foo *));

Why does the program work normally if these is not any function call in main()?

The definition of foo will cause main() to have a large stack frame at runtime. If you does not call any function in main(), this large stack frame will not be actually allocated or accessed (the entrance code of main() only make sure that amounts of memory be reserved by manipulating some registers and memory cells); but if you call a function in main(), the calling itself will try to access some addresses in that main() stack frame, because of stack overflow, those addresses may not be valid, this will cause SIGSEV be sent.

If you disassemble and compare the working and not-working versions of this program, this would be obvious. You could also find it out by stepping through the instructions of not-working main() one by one.


Without function call in main():

0x00001ff0 <main+0>:    push   %ebp
0x00001ff1 <main+1>:    mov    %esp,%eax
0x00001ff3 <main+3>:    mov    %esp,%ebp
0x00001ff5 <main+5>:    sub    $0x2625a10,%esp
0x00001ffb <main+11>:   mov    %eax,%esp
0x00001ffd <main+13>:   leave  
0x00001ffe <main+14>:   ret  

Call exit() in main():

0x00001fe0 <main+0>:    push   %ebp
0x00001fe1 <main+1>:    mov    %esp,%ebp
0x00001fe3 <main+3>:    sub    $0x2625a28,%esp
0x00001fe9 <main+9>:    movl   $0x0,(%esp)    <==== This causes segfault.
0x00001ff0 <main+16>:   call   0x3000 <dyld_stub_exit>
Lee Duhem
  • 14,695
  • 3
  • 29
  • 47
  • 1
    Also, check to see if `bar == NULL`. If so, the `malloc()` call failed. Also, later, clean up this memory via `free(bar);bar=NULL;` – Cloud Mar 19 '14 at 16:18
  • leeduhem - but why without the while (printf) loop, it works? any ideas? – knostika Mar 19 '14 at 16:19
  • @user3355469 If you did not call any function in your `main()`, the definition of `foo` only causes `main()` will have a large stack frame, but does not actually allocate that large stack frame. However, if you call any function in `main()`, this calling itself will need to access part of the `main()` stack frame, and this access will cause a SIGSEV (because try to access a invalid address). If you disassemble your different versions of program, and compare (or do instruction step in gdb) them, this would be obviously. – Lee Duhem Mar 19 '14 at 16:52
  • i think i should use gdb - but currently i am just using eclipse (though it uses gdb from the background for debugging i think)... but maybe i will have more memory visibility using gdb commandline... i have not used gdb in this manner yet though... – knostika Mar 19 '14 at 17:01
3

Stack overflow is causing sigsegv. There's no need of a while loop. A single printf will cause stack overflow.
Local variables are created on the stack. The variable foo is using huge space on the stack. Stack is also used to store return addresses in function calls. So both of them together will cause a stack overflow. foo uses up almost all the space in the stack. Calling printf overflows the stack
You should allocate on the heap using malloc.

avmohan
  • 1,820
  • 3
  • 20
  • 39
  • hi v3ga - can you please elaborate? – knostika Mar 19 '14 at 16:07
  • two things - first how will i know that before hand, second but why if i just comment the printf, just like the edit i did above - it does not sigsev? – knostika Mar 19 '14 at 16:13
  • No one allocates such large arrays on the stack. You should use heap to allocate such large arrays. – avmohan Mar 19 '14 at 16:14
  • 1
    You don't have a problem without `printf` most likely because in fact you never use that array, so compiler removes it completely. Actual answer may only come from analysing disassembly of what exactly compiler have generated. – keltar Mar 19 '14 at 16:17
  • thanks alot i appreciate it - so i guess my main thing here is that i make sure i don't exhaust my stack, and that i know the limit of the stack - is there a way programmatically for me know i am reaching stack limit? – knostika Mar 19 '14 at 16:17
  • @keltar Even with printf, notice that the array is not accessed in printf – avmohan Mar 19 '14 at 16:17
  • You can get/set stack size in linux using getrlimit/setrlimit functions. Dunno about windows – avmohan Mar 19 '14 at 16:19
  • Yeah, sorry. Probably just confuses compiler. Can't tell without disassembly. As for getting current stack usage - is is very platform-specific. It surely could be done, but what's a point? If you can proceed even when stack is almost full - then you don't actually need it. If you can't - well, you can't, it wouldn't help. – keltar Mar 19 '14 at 16:20
  • as you may see i am a beginner on this - i am just actually exploring virtual memory... thanks for your tip about using heap memory instead... something for me to explore... – knostika Mar 19 '14 at 16:21
  • yep - now it makes sense- if i remember it right, the stack is a fixed memory segment- allocated on program start up... while the virtual memory can be sized/resized programmatically using malloc... the struct pointer array should have been allocated from malloc(heap)... instead of just adding it in the stack (program text) – knostika Mar 19 '14 at 16:39
1

Stack size is the problem here, as others have pointed out. Check out C/C++ maximum stack size of program for more details.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270