Is segfault guaranteed when dereferencing null poi

2020-03-25 09:47发布

In the C/C++ code below

int * a = malloc(N * sizeof(int)); // suppose return value is NULL
a[2] = 1;

In the case where malloc returns NULL, do I have a guarantee that segfault will occur or is the behavior unpredictable?

标签: c++ c null
5条回答
够拽才男人
2楼-- · 2020-03-25 10:30

No, it's not guaranteed.

For example, what if you run this (evil) code prior to your example:

mmap( ( void *) 0, ( size_t ) 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 );

That maps an anonymous page with read/write permissions at address 0.

查看更多
劳资没心,怎么记你
3楼-- · 2020-03-25 10:33

A segfault is not guaranteed by the C standard.

Dereferencing an invalid pointer invokes undefined behavior.

查看更多
家丑人穷心不美
4楼-- · 2020-03-25 10:40

No, the program is not guaranteed to segfault. Dereferencing a pointer to which an invalid value has been assigned is undefined behaviour, and the standard clearly says that undefined behaviour imposes no requirements. It may terminate program execution but it does not have to; it may even ignore the situation completely:

3.4.3 undefined behavior

1 behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

查看更多
We Are One
5楼-- · 2020-03-25 10:47

In a word, no.

To quote from Wikipedia:

Dereferencing the NULL pointer typically results in an attempted read or write from memory that is not mapped - triggering a segmentation fault or access violation. This may represent itself to the developer as a program crash, or be transformed into an exception that can be caught. There are, however, certain circumstances where this is not the case. For example, in x86-real mode, the address 0000:0000 is readable and usually writable, hence dereferencing the null pointer is a perfectly valid but typically unwanted action that may lead to undefined but non-crashing behaviour in the application. Note also that there are occasions when dereferencing the NULL is intentional and well defined; for example BIOS code written in C for 16-bit real-mode x86 devices may write the IDT at physical address 0 of the machine by dereferencing a NULL pointer for writing. It is also possible for the compiler to optimize away the NULL pointer dereference, avoiding a segmentation fault but causing other undesired behavior...

In C, the behavior of dereferencing a null pointer is undefined.

Also check out this wild example of a null class pointer dereferenced, but which still works just fine.

Basically, don't do this, but then you knew that :)

查看更多
不美不萌又怎样
6楼-- · 2020-03-25 10:48

You do not have any guarantee; dereferencing a null pointer is undefined behavior. It will probably result in a segfault, unless you have certain optimizations turned on or are compiling on a weird platform, in which case it might start executing some other function with effectively random arguments, generate some other error, grab some value out of memory, or make demons fly out of your nose, or skip that line entirely. The only one of those which I’d even be surprised by is the next-to-last.

In more detail:

  • With certain optimizations, the compiler might detect that you’re trying to dereference NULL, decide “that isn’t allowed, so that code path can never happen”, and get rid of the usual function cleanup code; this would result in your program sliding into whatever function happens to be next in the output binary.
  • If the linker doesn’t put a function next but some other type of value, it might try to execute that, which will either result in a problem because it generated an illegal instruction, or a problem because that other object might be marked non-executable by the operating system.
  • Some embedded systems don’t have virtual memory, so actually have some values at memory address zero and will happily give you whatever happens to be there.
  • To the best of my knowledge, nasal demons would require hardware support which most computers don’t provide, so they’re an unlikely result. If it happens, though, don’t say you weren’t warned.
  • As pointed out by @hvd in the comments, the compiler might just skip the line as a dead store.

If for some reason you want to generate a segfault, a much better way to do that is with

kill(getpid(), SIGSEGV);

(after including the appropriate headers). This sends the segfault signal without any actual segmentation violation. If you do want to actually commit a segmentation violation, you’re best bet is to map and then unmap some page (this is OS-dependent) and then try to access a pointer into that page.

查看更多
登录 后发表回答