NlightNFotis
NlightNFotis

Reputation: 9803

What does this mean?: *(int32 *) 0 = 0;

In the following piece of code, what does *(int32 *) 0 = 0; mean?

void
function (void)
{
  ...

  for (;;)
     *(int32 *) 0 = 0;     /* What does this line do? */
}

A few notes:

Upvotes: 37

Views: 4972

Answers (8)

user
user

Reputation: 6947

The original IBM PC stored the interrupt vector table in the lowest 1 KiB of memory. Hence actually writing a 32-bit value to the address 0 on such an architecture would overwrite the address for INT 00h. INT 00h looks unused in the PC.

On basically anything modern (meaning in x86/x86-64 parlace anything running in protected or long mode), it will trigger a segmentation fault unless you are in ring 0 (kernel mode) because you are stepping outside of your process' allowed address dereference range.

As the dereference is undefined behavior (as already stated), a segmentation fault is a perfectly acceptable way to handle that situation. If you know that on the target architecture a zero address dereference causes a segmentation fault, it's seems to be a pretty sure way to get the application to crash. If exit() returns, that's probably what you want to do, since something just went horribly wrong. That the code is from a particular compiler's runtime means whoever wrote it can take advantage of knowledge of the internal workings of the compiler and runtime, as well as tailor it to the specific target architecture's behavior.

Upvotes: 3

Mark Hurd
Mark Hurd

Reputation: 10931

It could be that the compiler doesn't know exit() doesn't return, but it does know this construct does not return.

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 223254

Since the OP states the code was written by experienced compiler engineers, it is possible this is the intent of the code:

  • *(int32 *) 0 = 0; is recognized by this specific C implementation as code that causes behavior not defined by the C standard and known to this implementation to be illegal.
  • The for (;;) additionally indicates that this code is never exited.
  • The compiler engineers know that the optimizer will recognize this code and deduce that it may be “optimized away”, because any program that reaches this code is permitted to have any behavior, so the optimizer may choose to give it the behavior as if the code is never reached.1

This sort of reasoning is possible only if you have specific knowledge of the internal operation of a C implementation. It is the sort of thing a compiler engineer might include in special headers for a C implementation, perhaps to mark that certain code (such as code after an abort call) is never reached. It should never be used in normal programming.


1 For example, consider this code:

if (a)
    for (;;)
        *(int 32 *) 0 = 0;
else
    foo();

The compiler can recognize that the then-clause is permitted to have any behavior. Therefore, the compiler is free to choose what behavior it has. For simplicity, it chooses it to have the same behavior as foo();. Then the code becomes:

if (a)
    foo();
else
    foo();

and can be further simplified to:

foo();

Upvotes: 27

Scotty Bauer
Scotty Bauer

Reputation: 1277

The code is doing the following:

   for (;;) // while(true)
     *(int32 *) 0 = 0; // Treat 0 as an address, de-reference the 0 address and try and store 0 into it.

This should segfault, null pointer de-reference.

EDIT

Compiled and ran for further information:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(void){
  *(int32_t *) 0 = 0;
  printf("done\n");
  return 0;
}

gcc -g null.c; ./a.out

Program received signal SIGSEGV, Segmentation fault.
0x00000000004004cd in main () at null.c:7
7         *(int32_t *) 0 = 0;

Upvotes: 33

evilruff
evilruff

Reputation: 4085

In fact that this code seg-faulting doesn't explain why it's exists =)

I think that's from runtime of some MCU.. and reason it is there because if program execution will get to this point such instruction will either initiate software reset for an MCU, so program will be restarted (which is common practice in embedded development) OR if MCU configured with hardware watchdog, force MCU restart because of hardware watchdog and never ending loop.

Main goal of such constructions to invoke an interrupt which can be handled either by OS or by hardware for initiate certain actions.

Knowing that its x86 it will depend on a CPU mode... in Real Mode nothing will really happened instantly if there is no watchdog, at address 0 there is an address of 'divide by 0' handler, so if it's some old MS-DOS or embedded x86 runtime it will change an address of the 'Divide by 0' handler to 0, so as soon as it happens and this interrupt is not masked CPU will jump to location 0:0 and probably will just restart because of illegal instruction.. if it's protected or VM x86 code then it's a way to notify OS or any other supervisor that there is a problem in runtime and software should be 'killed' externally.

Upvotes: 21

Klash
Klash

Reputation: 166

Mike's comment is pretty well correct: it's storing the VALUE zero at the ADDRESS 0.

Which will be a crash on most machines.

Upvotes: 3

Sam
Sam

Reputation: 7868

for(;;) is equivalent to while(1),

*(int32 *) 0 = 0;writes 0 to a dereferenced null pointer, which is expected to cause a crash, but actually won't at all times on certain compilers: Crashing threads with *(int*)NULL = 1; problematic?

Upvotes: 6

Medinoc
Medinoc

Reputation: 6608

It's an infinite loop of undefined behavior (dereferencing a null pointer). It's likely to crash with a segfault on *n*x or Access Violation on Windows.

Upvotes: 3

Related Questions