tags:

views:

277

answers:

6

I am getting a strange result in the following C code.

int main()
{
    int *p = (int *) malloc(100);
    p[120] = 5;
    printf("\n %d", p[120]);
}

Since I have allocated only 100 bytes, this code should give cause a segmentation fault. However, it prints '5' and does not give any runtime error. Can anyone please explain the reason?

A: 

You are writing into memory which you have not allocated. The program might eventually terminate due to the effects of heap corruption if its run time were sufficiently long.

William Bell
+14  A: 

No, the code should not (necessarily) give a segfault. A segfault occurs when you attempt to access a virtual memory page that is not allocated to your process.

The "heap" or "free store" is a region of virtual memory pages owned by your process. The malloc() API sub-divides this region into blocks and returns a pointer to the block.

If you address beyond the end of the block to which you have a pointer, you will usually access memory that is part of the heap, but not part of your allocated block. In this way, you can corrupt other heap blocks or even the data structures which malloc() uses to define the heap.

For more information on heap corruption, and methods to detect it in the debug version of your code, this is a great book:

Writing Solid Code: Microsoft's Techniques for Developing Bug-Free C Programs by Steve Maguire alt text

An addendum for the pedantic: In rare cases, by accessing memory beyond the end of a heap block, you may access memory that is not part of the heap. In these cases, you may get the segmentation fault you expected. You might also corrupt some other data structure than the heap. It's really a matter of chance. However, the heap itself is very large compared to typical heap blocks, so 99% of the time code such as your example will corrupt the heap. The example you provide falls into that 99% case.

Heath Hunnicutt
Actually, since he asked to change 20 bytes past the end of the stack, depending on the architecture and surrounding code he could instead hose the stack, or even change the program itself. The behavior is truly undefined.
T.E.D.
T.E.D. That is only "sort of" true. He is no doubt using a machine with a virtual memory page size. Presumably executable code has different VM protection than heap. I would wager he is on such a system because the C standard library malloc() function exists. What you write is true, however, in particular on the Radio Shack Model III running TRS-DOS on a Z-80. ;)
Heath Hunnicutt
And yes, even on a VM page system, what you write could possible happen. It just isn't that likely and it isn't very pedagogical to go into that detail that rarely matters. Address the problem at the level at which it is stated. Avoid pedantry.
Heath Hunnicutt
@T.E.D. Actually, you wrote "stack" and I read "heap." What you wrote is straight-up mistaken.
Heath Hunnicutt
+5  A: 

Invalid memory accesses won't always cause a segmentation fault, bus error, or other crash. For example, if there's another block allocated immediately after your array, you're changing the values in that block -- which could be anything.

John Millikin
+1  A: 

You're writing to uninitialized memory; this is allowed in C, it's just not a good idea. This sort of thing shouldn't necessarily cause a segmentation fault.

McWafflestix
+2  A: 

No, it can give a segfault, but only if the memory is outside your process. Otherwise it will just modify some other area of your program memory. C doesn't check for this, or protect you in any way, even in obvious cases like the above. Many many software crackers use this "feature" of C to essentially rewrite a program that has elevated privs, and give themselves control over your machine. It is called a buffer overflow exploit.

This is why C (and C++) should really be avoided for new software in preference for safer languages like Ada.

T.E.D.
I know the last sentence will get me voted negative. I don't care. Its true.
T.E.D.
+1 from me. I completely agree.
Wayne
A: 

Common causes of segmentation fault:

  • dereferencing pointer with invalid value
  • dereferencing null pointers
  • attempting to write into a read-only segment
  • free-ing improper pointers or un-owned blocks.

    int *x=0;

    x = 200; / causes segmentation fault */

Segfaults are generated by MMU exceptions based on what is determined to be an illegal memory access. Depending on how the OS structures its memory, one memory access on an OS might be legal (although wrong) and on another OS it might be illegal.

prime_number