我有以下代码:
main ()
{
printf("Hello world !");
*(int *)(0) = 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译此代码并运行时,它没有将字符串打印到控制台.在那之后,我修改了一点:
main ()
{
printf("Hello world !\n");
*(int *)(0) = 0;
}
Run Code Online (Sandbox Code Playgroud)
而且,它工作!
我认为背后的奥秘是*(int *)(0) = 0;但不知道为什么!
PS.我正在使用gcc 4.8.2进行编译.
直接原因是FILE *操作被缓冲,stdout特别是通常是行缓冲的(至少是交互式的).如果\n看不到并且fflush在崩溃之前没有显式调用,则实际上不会将任何内容写入底层文件描述符.
更大的问题是取消引用NULL指针是不明确的行为.对可能发生的事情绝对没有限制.如果编译器可以证明printf将始终返回,则允许UB在调用之前传播到整个mainUB.也就是说,编译器很难证明这一点,特别是因为FILE通常涉及vtable,它实际上并不是真的.但关键是你甚至不能相信UB要等到特定的时间.