views:

131

answers:

3

Hello,

In the code snippet, I expected a segmentation fault as soon as trying to assign a value to count[1]. However the code continues and executes the second for-loop, only indicating a segmentation fault when the program terminates.

#include <stdio.h>

int main()
{
        int count[1];
        int i;

        for(i = 0; i < 100; i++)
        {
                count[i] = i;
        }
        for(i = 0; i < 100; i++)
        {
                printf("%d\n", count[i]);
        }
        return 0;
}

Could someone explain what is happening?

Reasons for edit: Improved the example code as per comments of users, int count[0] -> int count[1], too avoid flame wars.

+15  A: 

You're writing beyond the bounds of the array. That doesn't mean you're going to get a segmentation fault. It just means that you have undefined behavior. Your program's behavior is no longer constrained by the C standard. Anything could happen (including the program seeming to work) -- a segfault is just one possible outcome.

In practice, a segmentation fault occurs when you try to access a memory page that is not mapped to your process by the OS. Each page is 4KB on a typical x86 PC, so basically, your process is given access to memory in 4KB chunks, and you only get a segfault if you write outside the current chunk.

With the small indices you're using, you're still staying within the current memory page, which is allocated to your process, and so the CPU doesn't detect that you're accessing memory out of bounds.

jalf
+2  A: 

Your code is broken:

seg.c:5: warning: ISO C forbids zero-size array ‘count’

Always compile with high warning levels, for example -Wall -pedantic for GCC.

Edit:

What you are effectively doing is corrupting mains function stack frame. Since stack nowadays pretty much always grows down, this is what's happening:

  • First loop overrides stack memory holding main parameters and return address to crt0 routines.
  • Second loop happily reads that memory.
  • When main returns the segmentation fault is triggered since return address is fubar-ed.

This is a classic case of buffer overrun and is the basis of many network worms.

Run the program under the debugger and check the addresses of local variables. In GDB you can say set backtrace past-main so backtrace would show you all the routines leading to main.

By the way, the same effect could be achieved without zero-length array - just make its size smaller then number of loop iterations.

Nikolai N Fetissov
I know that the code is incorrect. It is for illustrative purposes. You did not answer the question.
pfdevil
Complaints about the question are best written as a comment on the question. (Click "add comment".)
Daniel Newby
@Daniel, have you ever tried laying out long code lines in comments? Comments formatting sucks.
Nikolai N Fetissov
@pfdevil, if you know that code is incorrect - state it in the question. Otherwise you are asking for lots of "this is undefined behavior` answers.
Nikolai N Fetissov
He did say "I expected a segmentation fault", which implies he knew the code was incorrect.
Nick Lewis
These are two different kinds of "incorrect".
Nikolai N Fetissov
@pfdevil, Usually you illustrate your point with correct code, and not (as you act like) with *deliberately* written wrong code. That's weird.
Johannes Schaub - litb
+1 for explaining stack corruption in this case.
Martin Wickman
+3  A: 

When you write beyond the array bounds, you are probably still writing data into the area of memory under the control of your process; you are also almost certainly overwriting memory used by other software, such as heap or stack frame management code. It is only when that code executes, such as when the current function attempts to return, that your code might go awry. Actually, you really hope for a seg fault.

GregS