分配uninitilialized void *指针

时间:2014-08-11 05:53:13

标签: c gcc glibc

#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;会突然导致细分错误。为什么呢?

4 个答案:

答案 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没有安全性。