#include <stdio.h>
void wat(void *ptr){
*(int*)ptr = 0x4A424F4B;
return;
}
int main(int argc, char **argv){
FILE *wtf = fopen("wat", "wb");
void *ptr;
wat(ptr);
return 0;
}
实际编译并执行且没有错误,您甚至可以fwrite
*(int*)ptr
的内容获得0x4A424F4B
。但是,当您删除此行时:
FILE *wtf = fopen("wat", "wb");
*(int*)ptr = 0x4A424F4B;
会突然导致细分错误。为什么呢?
答案 0 :(得分:6)
从技术上讲,您的代码有undefined behaviour。
发生使用您的特定编译器不会在您的特定平台上爆炸,因为未初始化的ptr
恰好包含某些可写内存的地址。由于我们不知道ptr
指向的位置,因此我们无法知道该任务有何危害。
移动物体会改变地址,事情会“破裂”(严格来说,它们并不是真正起作用)。
答案 1 :(得分:3)
这是未定义的行为,所以任何事情都可能发生。
可能发生了什么,用这一行
FILE *wtf = fopen("wat", "wb");
有效的指针值留在堆栈中。然后未初始化的ptr
得到它。但同样,未定义的行为,你不应该依赖它。
答案 2 :(得分:2)
*(int*)ptr = 0x4A424F4B;
表示将整数值0x4A424F4B
写入整数指针ptr
指向的地址。由于您未初始化ptr
,因此未定义其行为。因此,它在某些情况下起作用的事实是无关紧要的。
答案 3 :(得分:1)
它编译,但你收到警告:
$ gcc -Wall -o ptr ptr.c
ptr.c: In function ‘main’:
ptr.c:9:11: warning: unused variable ‘wtf’ [-Wunused-variable]
FILE *wtf = fopen("wat", "wb");
^
ptr.c:11:5: warning: ‘ptr’ is used uninitialized in this function [-Wuninitialized]
wat(ptr);
^
如果启用地址清理程序,它将无法执行而不会出现错误:
$ gcc -fsanitize=address -o ptr ptr.c
$ ./ptr
=================================================================
==3280==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000040080d sp 0x7ffffa1f4940 bp 0x7ffffa1f4950 T0)
#0 0x40080c in wat (/tmp/ptr+0x40080c)
#1 0x400843 in main (/tmp/ptr+0x400843)
#2 0x7fa048110b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
#3 0x4006f8 (/tmp/ptr+0x4006f8)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 wat
==3280==ABORTING
但是,是的,默认情况下,C没有安全性。