0

I'm stunned, why does this code give me a segmentation fault?

#include <stdio.h>

#define LIMIT 1500000

typedef struct {
    int p;
    int a;
    int b;
} triplet;

int main(int argc, char **argv) { 
    int i;
    triplet triplets[LIMIT];

    for (i = 0; i < LIMIT; i++) {
        triplets[i].p = 9; // remove this line and everything works fine
    }

    printf("%d\n", triplets[15].p);

    return 0; 
}

EDIT: After changing LIMIT to 150 I no longer get a segmentation fault, it prints random numbers instead.

EDIT2: Now I know what the site name stands for :) I made the array global and everything works fine now.

orlp
  • 112,504
  • 36
  • 218
  • 315

2 Answers2

10

Stack overflow! Allocating 1500000 records at 12 bytes per record (assuming 4-byte int), requires more than 17 MB of stack space. Make your triplets array global or dynamically allocate it.

As to your edit - shrinking the array will probably stop the stack overflow, but your printf() call will still print uninitialized data - triplets[15].p could be anything at the time you print it out.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • I'm not too good with C, how would I change the code to avoid this? – orlp Jan 11 '11 at 23:49
  • Not to mention that you're trying to access uninitialized memory. Make sure you assign `triplets[15].p` to something before you try reading it. – Sam Dufel Jan 11 '11 at 23:51
  • The line that was causing me the trouble was the line where I was going to initialize everything. But I got presented with a nice segmentation fault. The < 5 in the for loop was a random test of mine. – orlp Jan 11 '11 at 23:52
  • 1
    @nightcracker, most of the time the stack grows 'downward' in memory - that is, from high addresses to low ones. So when you allocate 17 MB on the stack, like your program does, the base of the array is past the end of the stack and writing to the lower entries in the array causes the crash. If you started initializing from the other end of the array (reverse the loop order), you'd probably not see the error until much later in the initialization process. – Carl Norum Jan 11 '11 at 23:55
  • Thanks, I'll remember that for whenever these problems happen again :) – orlp Jan 11 '11 at 23:56
4

When you do

triplet triplets[LIMIT];

you're allocating that on the stack. Which is apparently too big for your system.

If you do

triplet* triplets=(triplet*)malloc(LIMIT*sizeof(triplet));

you'll allocate it on the heap and everything should be fine. Be sure to free the memory when you're done with it

free(triplets);
miked
  • 3,458
  • 1
  • 22
  • 25
  • Note that the OP could also preserve scope and allocate in the data segment instead of stack by changing the array declaration to `static triplet triplets[LIMIT];` which is likely a better option than making it a public global. The `malloc()` solution is probably the better approach in the long run, however. – RBerteig Jan 11 '11 at 23:57
  • 1
    Also, there isn't any need to cast the malloc return type in C. http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc –  Jan 11 '11 at 23:59