这是什么意思?:*(int32*)0 = 0;

Nli*_*tis 37 c

在下面的代码中,*(int32 *) 0 = 0;含义是什么?

void
function (void)
{
  ...

  for (;;)
     *(int32 *) 0 = 0;     /* What does this line do? */
}
Run Code Online (Sandbox Code Playgroud)

几点说明:

  • 代码似乎无法访问,因为在该特定代码段之前有一个退出语句.
  • int32typedef'但你不应该太在意它.
  • 对于任何感兴趣的人来说,这段代码来自编译器中语言的运行时.

Sco*_*uer 33

代码正在执行以下操作:

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

这应该是segfault,null指针de-reference.

编辑

编译并运行以获取更多信息:

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

int main(void){
  *(int32_t *) 0 = 0;
  printf("done\n");
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Hrishi:我不知道 - 但是在任何现代的多处理操作系统(Unix,Linux,Windows,...)上,一个无特权的程序不能破坏操作系统级的数据结构(除非操作系统有错误,但是这样一个bug不太可能被这些简单的代码触发).通常,每个进程都有自己的虚拟地址空间; 您的进程的地址0(如果存在)与内核的地址0或任何其他进程无关. (26认同)
  • @Hrishi:在任何合理的系统上(除了一些非常小的嵌入式平台),故障只会影响一个程序. (3认同)

Eri*_*hil 26

由于OP声明代码是由经验丰富的编译工程师编写的,因此这可能是代码的意图:

  • *(int32 *) 0 = 0; 被这个特定的C实现识别为导致C标准未定义且该实现已知的行为非法的代码.
  • for (;;)还指示该代码永远不会退出.
  • 编译器工程师知道优化器将识别此代码并推断它可能"被优化掉",因为任何到达此代码的程序都被允许具有任何行为,因此优化器可以选择为其提供行为,就像代码一样永远不会到达.1

只有当您具有C实现的内部操作的特定知识时,可能进行这种推理.这是编译器工程师可能包含在C实现的特殊头文件中的事情,可能是为了标记某些代码(例如abort调用后的代码)永远不会到达.它绝不应该用于普通编程.


1例如,请考虑以下代码:

if (a)
    for (;;)
        *(int 32 *) 0 = 0;
else
    foo();
Run Code Online (Sandbox Code Playgroud)

编译器可以识别允许then子句具有任何行为.因此,编译器可以自由选择它具有的行为.为简单起见,它选择它具有相同的行为foo();.然后代码变成:

if (a)
    foo();
else
    foo();
Run Code Online (Sandbox Code Playgroud)

并可进一步简化为:

foo();
Run Code Online (Sandbox Code Playgroud)


evi*_*uff 22

事实上,这段代码seg-faulting并没有解释为什么它存在=)

我认为这是来自某些MCU的运行时间...并且它的存在是因为如果程序执行到了这一点,这样的指令将启动MCU的软件复位,因此程序将重新启动(这是嵌入式开发中的常见做法)或者如果MCU配置了硬件看门狗,则由于硬件看门狗和永不结束循环而强制MCU重启.

这种结构的主要目标是调用中断,该中断可由OS或硬件处理以启动某些操作.

知道它的x86它将取决于CPU模式......在实模式下如果没有看门狗就不会立即发生任何事情,在地址0处有一个"除以0"处理程序的地址,所以如果它是一些旧的MS- DOS或嵌入式x86运行时它会将'Divide by 0'处理程序的地址更改为0,因此只要它发生并且此中断未被屏蔽,CPU将跳转到位置0:0并且可能因非法指令而重新启动..如果它受到保护或VM x86代码,那么它是一种通知操作系统或任何其他主管在运行时出现问题的方法,软件应该在外部被"杀死".


Sam*_*Sam 6

for(;;)相当于while(1),

*(int32 *) 0 = 0;将0写入一个取消引用的空指针,该指针预计会导致崩溃,但实际上并不会在某些编译器上发生崩溃:崩溃线程带*(int*)NULL = 1; 有问题?