繁体   English   中英

为什么GCC seg会在教科书上没有clang的情况下出错?

[英]Why does GCC seg fault where clang does not on a textbook exercise?

使用Adam Hoover的“使用C和Unix进行系统编程”来学习C。 我遇到了来自第4章的问题,这使我非常困惑。 问题如下:

在下面的代码中,到达的第一个printf()产生输出“ 14”,但是第二个printf()可能导致总线错误或分段错误。 为什么?

书中的原始代码:

main()
{ 
  int *p;
  funct(p);
  printf("%d\n",*p);
}
funct(int *p2)
{
  p2=(int *)malloc(4);
  *p2=14;
  printf("%d\n",*p2);
}

我稍作修改的“调试”(printf所有东西)版本:

#include <stdio.h>
#include <stdlib.h>

void funct(int *p2);

int main(){
    int *p;
    printf("main p - address: %p\n", p);

    funct(p);
    printf("main p - address: %p\n", p);
    printf("main p value: %d\n", *p);
}  

void funct(int *p2){
    printf("funct (pre malloc) p2 - address: %p\n", p2);

    p2 = (int *)malloc(4);
    printf("funct (post malloc) p2 - address: %p\n", p2);

    *p2 = 14;
    printf("funct p2 value: %d\n", *p2);
}  

我已经使用gcc和clang(在ubuntu linux上)编译了此示例,并且clang不会为应该这样做的代码产生seg错误。 我对此感到困惑了一段时间,无法想象为什么或如何这样做。 欢迎任何有识之士。

谢谢。

int *p;
funct(p);
printf("%d\n",*p);

错了 p 通过值传递 因此,对函数进行的修改不会影响main p 并且取消引用未初始化的指针行为是未定义的。

您实际需要做的是-

funct(&p) ; // in main

void funct( int **p ){
   *p = malloc(sizeof(int));
   // ...
}

这是未定义的行为,不必导致崩溃(或任何其他特定行为)。 在这种情况下,编译器可以自由产生喜欢的任何代码。 既然您问了为什么clang产生的代码不会崩溃,所以我们需要深入研究该代码。 以下是在x86_64上使用-O3进行编译时产生的clang干线:

main:                               # @main
    pushq   %rbp
    movq    %rsp, %rbp              # Build stack frame
    movl    $.L.str, %edi
    movl    $14, %esi
    xorb    %al, %al                # no XMM registers used by varargs call
    callq   printf                  # printf(%edi = "%d\n", %esi = 14)
    movl    $.L.str, %edi
    xorb    %al, %al                # no XMM registers used by varargs call
    callq   printf                  # printf(%edi = "%d\n", %esi = ?)
    xorl    %eax, %eax
    popq    %rbp
    ret                             # return %eax = 0

由于p未初始化,因此clang今天选择将表达式*p完全编译为空。 这是合法的转换,因为clang可以证明表达式具有未定义的行为。 然后,在printf调用时(在我的机器上,恰好是-1 ),被打印的值就是%esi寄存器中最终的值。 这可能不是您所期望的,但这就是不确定行为的本质!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM