0

As far as I understand, a segfault is raised whenever a program attempts to access unauthorized memory.

The following code allocates a one-int memory block to p, and then tries to write at some unknown address.

#include <stdlib.h>

int main(void)
{
    int* p = malloc(sizeof(int));

    p[1000] = 12;

    return 0;
}

Why does this code raise no segmentation fault, while it tries to access this somewhat random address?


Related

How undefined is undefined behavior? - Explains undefined behaviours, but not why that p[1000] = 12 instruction does not raise a segfault.

Community
  • 1
  • 1
Right leg
  • 16,080
  • 7
  • 48
  • 81
  • 1
    Possible duplicate of [How undefined is undefined behavior?](http://stackoverflow.com/questions/7961067/how-undefined-is-undefined-behavior) – StoryTeller - Unslander Monica Dec 22 '16 at 05:52
  • "but not why that `p[1000] = 12` instruction is legal." - It's not. It's undefined. – milleniumbug Dec 22 '16 at 06:29
  • the variable 'p' is pointing somewhere in the heap. The heap has (at least) one page (typically 4096bytes) of memory allocated and set to read/write mode. So the act of writing to that memory does not trigger a seg fault event. – user3629249 Dec 23 '16 at 21:13

5 Answers5

1

By doing p[1000] = 12;, you are simply putting a value at the address (p+1000). There is nothing that should result into segfault. The address could be a valid one, though not legitimately acquired by p.

Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
1

When you start your program, OS will divide the programs memory into readable (code section) and writable (data section as well as heap). Now it will depend on the address stored in the pointer you are d-referencing.

If it points to a valid writable memory then no segmentation fault exception will be raised, otherwise a segmentation fault exception will be raised.

Sumit Gemini
  • 1,836
  • 1
  • 15
  • 19
1

The following code allocates a one-int memory block to p, and then tries to write at some unknown address.

It's not an "unknown" address; the address is p+4000 on a system with sizeof(int) == 4.

Most current operating systems use demand paging. On such a system, the very first call to malloc is likely to allocate a fresh page of memory. Common page size is 4096, and writing anywhere within this (writable) page will not produce a segmentation fault.

This program on the other hand very likely will produce a segmentation fault:

int main(void)
{
    int* p = malloc(sizeof(int));
    int j;

    for (j = 1000; j < 100000; j++) p[j] = 12;

    return 0;
}
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Thanks for explaining the paging concept. Still, how "likely" is malloc to allocate a new page? – Right leg Dec 22 '16 at 06:34
  • @Rightleg For the very first malloc? Exceedingly likely. – Employed Russian Dec 22 '16 at 06:35
  • Ok, let's say it is certain, and anyway you answered my question pretty will. Still, I'm curious about this somehow uncertain behaviour... – Right leg Dec 22 '16 at 06:37
  • 1
    @Rightleg I don't understand your curiosity. Your program has undefined behavior, and may explode randomly. Are you similarly curious about the game of Russian roulette? – Employed Russian Dec 22 '16 at 06:43
  • No, I'm curious about how C works. Whatever, I'll find it by myself, thanks you still for your help. – Right leg Dec 22 '16 at 06:45
  • @Rightleg: It's possible for `malloc()` to allocate a 4K page and return a pointer to 4 bytes at the end of the page. In that case, you could get a fault from writing to or reading from `p[1]` (but not for taking its address). Basically, don't play with fire; you'll get burnt. Typically, the burning occurs when you're demonstrating your latest program to your boss, your boss's boss, your boss's boss's boss and the company's most important customer. That tends to be painful. – Jonathan Leffler Dec 22 '16 at 06:50
  • @JonathanLeffler Indeed that is exactly what happens when one uses ElectricFence ;-) – Employed Russian Dec 22 '16 at 06:58
0

It all depends on what platform and what operating system you are running this on. If you compile this code and run it on a processor that does not have an MMU or MPU, then you will not get any exception / segmentation fault.

Matthieu
  • 16,103
  • 10
  • 59
  • 86
0

As far as I understand, a segfault is raised whenever a program attempts to access unauthorized memory.

Segfault raised when you're trying to access non paged memory block, there is nothing with authorization.

So does p[1000] points to non paged area? its undefined, however in your case, each dynamic memory allocation needs to be allocated in a memory page which is usually 4096 bytes in x86 systems, when youre calling malloc, it searches for free space in allocated pages, if no suitable memory block found (in previously allocated pages or freed ones), a new page request will be placed and a memory page will be allocated. now the malloc reserves the a portion of allocated page for you (if the size requested + headers are smaller than page size) and return the pointer of it.

Now when you're trying to access p[1000] you're actually accessing non reserved (not malloced) area, but the area is paged (remaining of previous allocation) so no segfault will be raised, but if you try access to bigger index like p[10000] probably you will get segfault.

There are more examples here

Community
  • 1
  • 1
e.jahandar
  • 1,715
  • 12
  • 30