为什么Linux不崩溃但输出随机字符串?

car*_*ter 1 c linux crash

char* getChar()
{
    //char* pStr = "TEST!!!";
    char str[10] = "TEST!!!";
    return str;
}
int main(int argc, char *argv[])
{
    double *XX[2];

    printf("STR is %s.\n", getChar());
    return (0);
}
Run Code Online (Sandbox Code Playgroud)

我知道堆栈中的临时变量不应该被返回.

实际上它会输出一个未定的字符串.

除了NULL-Pointer-Reference之外什么时候Linux崩溃?

Bas*_*tch 5

你有一些未定义的行为.阅读这个答案,了解这可能意味着什么.

如果您想要解释,您需要深入了解具体实施细节.这里......

这个carp.c文件(你的差不多,我改名getCharcarp,其中包括<stdio.h>)

 #include <stdio.h>
 char *carp() {
   char str[10] = "TEST!!!";
   return str;
 }
 int main(int argc, char**argv)
 {
   printf("STR is %s.\n", carp());
   return 0;
 }    
Run Code Online (Sandbox Code Playgroud)

编译gcc -O -fverbose-asm -S carp.c成一个良好的警告

carp.c: In function 'carp':
carp.c:4:8: warning: function returns address of local variable [-Wreturn-local-addr]
      return str;
      ^
Run Code Online (Sandbox Code Playgroud)

并加入此汇编代码(Debian/Sid/x86-64上的GCC 4.9.1)

    .text
.Ltext0:
        .globl  carp
        .type   carp, @function
carp:
.LFB11:
        .file 1 "carp.c"
        .loc 1 2 0
        .cfi_startproc
        .loc 1 5 0
        leaq    -16(%rsp), %rax #, tmp85
        ret
        .cfi_endproc
.LFE11:
        .size   carp, .-carp
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "STR is %s.\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB12:
        .loc 1 7 0
        .cfi_startproc
.LVL0:
        subq    $24, %rsp       #,
        .cfi_def_cfa_offset 32
        .loc 1 8 0
        movq    %rsp, %rsi      #,
.LVL1:
        movl    $.LC0, %edi     #,
.LVL2:
        movl    $0, %eax        #,
        call    printf  #
.LVL3:
        .loc 1 10 0
        movl    $0, %eax        #,
        addq    $24, %rsp       #,
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
.LFE12:
        .size   main, .-main
Run Code Online (Sandbox Code Playgroud)

正如您所注意到的,错误的carp函数是将堆栈指针返回减去16个字节.而main将打印会发生什么在那里.而在该位置发生的事情可能取决于很多因素(您的环境环境(7),用于堆栈的ASLR等等).如果您有兴趣了解究竟是什么在进入存储(和地址空间)main,潜入的execve(2) ,ld.so(8) ,你的编译器的信息crt0,你的内核源代码,您的动态链接程序的源代码,您libc源代码,x86-64 ABI等....我的生命太短暂,不需要花费很多时间来解释所有这些.

顺便说一句,请注意当地的初始化str"TEST!!!"已经正确地 优化,通过我的编译器了.

同时读取信号(7):在许多情况下你的进程可以终止(我不会像你那样称之为"Linux崩溃"),例如当从虚拟内存中的地址空间中取消引用指针时(参见本节),执行错误的机器代码等...