Siddique
Siddique

Reputation: 384

Why doesn't this code cause a segfault?

Why doesn't this segfault?

#include <stdio.h>
int main()
{
    int i;
    int arr[] = {1, 2, 3, 4};

    for(i=0;i<8;i++)
    {
        arr[i] = i;
        printf(" %d", arr[i]);
    }

    printf("\n");

    return 0;
}

But it does when I replace 8 with 9 in the for loop.

Note: I am trying it on 32 bit crunchbang linux

Upvotes: 3

Views: 177

Answers (3)

Nicu Stiurca
Nicu Stiurca

Reputation: 8687

@templatetypedef is right; he beat me to the answer. Undefined behavior doesn't necessarily mean segfault.

But I would like to offer some speculation as for why it segfaults for n=9 but not 8. Normally, variables like int i and int arr[] reside on the stack, which grows down. So, i might reside at address 0x4000, and if it's a 4 byte int, then arr[0] is at 0x4004, arr[1] is at 0x4008, and so on. In this case, the compiler will most likely have allocated 16 bytes for arr, and it may be using addresses below 0x4014 (the first byte after arr, ie the address of arr[5]). But there are typically other things on the stack besides the variables you manually declare. For instance, the arguments to the printf call are probably on the stack, and there could be other bookkeeping information. So if arr[9] coincides with the stack location that the compiler is using for something else, you will inadvertently clobber that information, which can lead to segfault.

Alternatively, if arr[8] is at the bottom of your stack frame allocated from the OS, then your OS will have configured your processor to literally refuse to execute any instruction to load or store a value from the address that coincides with arr[9]. I think this scenario is unlikely since stack sizes are usually 4KB or so, and for such a short program you should be nowhere near the end of the allocated stack.

Upvotes: 2

Hoffmann
Hoffmann

Reputation: 14719

templatetypedef answer is correct, this is a case of undefined behavior (which is not as uncommon as you might think) but I would like to add something:

9*sizeof(int) is not a power of 2. When compilers allocate memory they usually allocate in power of two bytes to prevent fragmentation of the heap.

You might wonder why it didn't instead allocate 4*sizeof(int) as that would be exactly what you asked. I'm not sure but it might be that the compiler allocates a couple of extra bytes or that it has a minimum amount of memory it will allocate for arrays. It depends on the compiler and the options you compiled your code with.

Try to run your code without optimizations (-O0 on the command line), it might instead allocate the exact amount of memory you need and segfault for i>=4.

I might be wrong though, I'm not sure that C compilers allocate static arrays in the heap or the stack.

Upvotes: 0

templatetypedef
templatetypedef

Reputation: 372814

Technically speaking, this program results in undefined behavior, meaning that there are absolutely no guarantees whatsoever about what this program is allowed to do. It could in principle format your hard drive, email nasty messages to all of your friends, set your computer on fire, or become sentient and enslave humanity.

In this case, the undefined behavior when n = 8 happens to not do anything bad, while the undefined behavior when n = 9 causes a segfault. Both are totally permissible behaviors for the program, but aren't at all guaranteed to be portable.

Hope this helps!

Upvotes: 14

Related Questions