-2

I'm trying to understand when any why a segmentation fault is generated. I wrote a small program which writes to an invalid random address.

I do not see a segmentation fault with this program -

 int main (void)
    {
    int c = 6;

    *(&c + 1000) = 5;

    printf ("0x%llx - %d\n", (unsigned long)&c, c);

    return 0;
    }

which outputs:

$ gcc segmentationFault.c
$ ./a.out
0x7ffc2f709b5c - 6
$

But, I get a seg fault with below code -

int main (void)
{
    int c = 6;

    *(&c + 3000) = 5;

    printf ("0x%llx - %d\n", (unsigned long)&c, c);

    return 0;
}

which produces:

$ gcc segmentationFault.c
$ ./a.out
Segmentation fault (core dumped)
$

Any explanation please?

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
UnClaimed
  • 5
  • 3
  • 7
    `UB` and `UB`. and *I do not see a segmentation fault* is one of the possible behavior under `UB` – Gaurav Sehgal Jun 08 '18 at 08:03
  • 3
    The "undefined" in "undefined behaviour" should be a hint, that the result is ... well, undefined. Don't expect anything specific. – Gerhardh Jun 08 '18 at 08:09
  • Have you tried reading https://stackoverflow.com/questions/2346806/what-is-a-segmentation-fault ? – AS Mackay Jun 08 '18 at 08:12
  • @AjayBrahmakshatriya While using a debugger is in general a good start, I don't see how it could help answering the question. – Gerhardh Jun 08 '18 at 08:57
  • The OS allocates memory in chunks which dimension is related to the processor paging dimension. In the first attempt the resulting address seems to be inside the allocated page, the second one is definitely outside and hits the guard page. Considering that paging generally use 4kb pages this should be reasonable. – Frankie_C Jun 08 '18 at 09:02
  • @Frankie_C, Is the memory allocated to stack segment dependent on page size? I'm running this program on linux. – UnClaimed Jun 08 '18 at 09:12
  • 1
    @UnClaimed in a system almost all memory is allocated through the Memory Manager using the paging mechanism. The stack isn't an exception apart for the fact that usually it grows downward. – Frankie_C Jun 08 '18 at 09:16
  • When you run across the freeway, there is no guarantee that you get hit by a car every time. That doesn't mean that running across the freeway is safe and something you should be doing. – Lundin Jun 08 '18 at 09:45

2 Answers2

3

A segmentation fault happens when your program accesses memory it isn't allowed to access. In your example, c+1000 could still be accessible to your program, while c+3000 isn't any more. However, since it's undefined behavior even *(c+1) could cause a segmentation fault.

tstenner
  • 10,080
  • 10
  • 57
  • 92
  • Thanks tstenner,Is there a way I could find the memory space accessible to my program? – UnClaimed Jun 08 '18 at 08:14
  • I think `(&c+1)` might be OK because C does not make reading one beyond the end of an array undefined behavior. The dereference will certainly bring trouble, though. Probably a moot point/distinction... Also see [Access element beyond the end of an array in C](https://stackoverflow.com/q/1021021/608639). – jww Jun 08 '18 at 08:17
  • 1
    @jww Does a variable count as a single element array? – Kami Kaze Jun 08 '18 at 08:21
  • 3
    @jww But `c` isn't an array. So definitely UB, right? – Spikatrix Jun 08 '18 at 08:30
3

There are different points in your question: one is what C language mandates, one is what your implementation does.

For the C language part: you are invoking Undefined Behaviour because as c is a single variable, &c is a pointer to the beginning of an array of size 1. So dereferencing &c + i is UB for any i != 0. UB means that from a language point of view anything can happen from returning an int to the definitive machine dead. Nothing more can be said here.

For the implementation part, a seg fault is an attempt to read an address that resides is a page that is not bound to the process in a system that gives pages of memory (with possibly virtual addresses, meaning a table mapping addresses in process space to addresses in physical memory). On Linux, the /proc/{pid}/maps and /proc/{pid}/pagemaps give information about the mapping for a process. More details on it on the following SO pages:

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252