【问题标题】:Why Clang supports dereferencing uninitialized pointer为什么 Clang 支持取消引用未初始化的指针
【发布时间】:2017-07-04 02:01:01
【问题描述】:

我试图了解我的 C 编程知识发生了什么变化。让我们从一个 CLASSICAL 问题开始(取消引用未初始化的指针):

int main( void ) {
    char *p;
    *p = 'a';
    printf( "%c\n", *p );
    return 0;
}

这显然是错误的!我知道。但是,当我在我的 MacOS 10.12 上运行此程序并将 LLVM Clang 8.1.0 实现为编译器时,它不仅无法检测到未初始化的指针,而且还在屏幕上显示字符“a”,就好像没有任何问题一样。至少我期待像“Segmentation Fault”这样的东西。

请稍等一下,看下面的代码:

int main( void ) {
    int i;
    char **strPtr;
    char *string = "Hello, world!";

    *strPtr = string;

    printf( "%s", *strPtr );
    return 0;
}

这一次,我使用 GCC-4.8.5 运行代码,它已经成功检测到第一个代码中的分段错误。令我沮丧的是,字符串“Hello, world!”在我运行代码后出现在屏幕上,好像它没有任何问题。

我想知道,既然 strPtr 也是一个指针(尽管是指向指针的指针),通过取消引用并为 strPtr 赋值,我不应该犯下与第一个代码中相同的错误吗?

【问题讨论】:

  • 告诉你的clang你希望它警告你这些东西(-Wall),并且它应该考虑这些警告错误(-Werror)。换句话说,使用例如clang -Wall -Werror source.c -o binary.
  • 您的指针未初始化。任何神编译器,包括 clang 都会警告无意义的转换。如果您忽略它们(或不启用推荐的警告),这不是编译器的错
  • "但也显示了结果" - 哪个结果?该代码没有任何意义,但会调用未定义的行为。
  • 当你编写一个调用未定义行为的程序时,any 行为对于 C 标准来说是“正确的”。不保证 Seg 故障。如果p 的垃圾内容碰巧是不在程序有效段内的地址,则会出现段错误。幸运的是,在您的情况下,p 的垃圾内容恰好指向分配给您的程序的读/写内存。
  • 诚然,编译器在未定义行为方面的差异解释了这个问题,但是您如何用第二段代码启发我?

标签: c pointers


【解决方案1】:

它不支持它;只是编译器假定你知道自己在做什么。

只是取消引用未初始化指针的行为是未定义

它似乎起作用是这种未定义行为的表现。

记住一句古老的格言:C 让你有能力射中自己的脚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-23
    • 2020-11-10
    • 2019-10-28
    • 2021-01-13
    • 2021-05-11
    • 2011-03-02
    • 2011-02-24
    • 1970-01-01
    相关资源
    最近更新 更多