【问题标题】:Assigning uninitilialized void* pointer分配未初始化的 void* 指针
【发布时间】:2014-08-11 05:53:13
【问题描述】:
#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; 会突然导致分段错误。为什么?

【问题讨论】:

标签: c gcc glibc


【解决方案1】:

从技术上讲,您的代码有undefined behaviour

碰巧不会在使用特定编译器的特定平台上崩溃,因为未初始化的ptr 恰好包含一些可写内存的地址。由于我们不知道ptr 指向的位置,因此我们无法知道该分配正在造成什么危害。

移动东西会改变地址,并且东西会“中断”(严格来说,它们一开始并没有真正起作用)。

【讨论】:

    【解决方案2】:

    这是未定义的行为,所以任何事情都可能发生。

    可能发生的事情是这样的

    FILE *wtf = fopen("wat", "wb");
    

    有效的指针值留在堆栈中。然后未初始化的ptr 得到它。但同样,未定义的行为,你不应该依赖它。

    【讨论】:

      【解决方案3】:
      *(int*)ptr = 0x4A424F4B;
      

      表示将整数值0x4A424F4B写入整数指针ptr指向的地址。由于您没有初始化 ptr,因此未定义其行为。因此,它在某些情况下有效的事实是无关紧要的。

      【讨论】:

        【解决方案4】:

        它可以编译,但你会收到警告:

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

        【讨论】:

        • 我没有收到任何警告,你在使用-Wall吗?
        • @M132 我展示了我使用的命令 :) 是的,我使用 -Wall。 C 编译器通常不会发出警告,除非您要求。
        • @M132 在实际项目中我实际上倾向于使用-Wall -Wextra -Wconversion
        猜你喜欢
        • 1970-01-01
        • 2015-11-08
        • 2014-09-10
        • 2020-12-31
        • 1970-01-01
        • 2015-10-26
        • 2021-01-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多