没有在C中获得分段错误

这是c代码:

char **s; s[334]=strdup("test"); printf("%s\n",s[334]);` 

我知道strdup会分配“test”,但是我们将把指针放到字符串“test”的情况下[334]没有分配,但是,这个代码就像一个魅力

编译器对我们来说太聪明了! 它知道printf("%s\n", some_string)puts(some_string)完全相同,因此它可以简化

 char **s; s[334]=strdup("test"); printf("%s\n",s[334]); 

 char **s; s[334]=strdup("test"); puts(s[334]); 

然后(假设没有UB)再次相当于

 puts(strdup("test")); 

因此,偶然发生了段故障(此时)。

您的代码显示未定义的行为。 这并不意味着它会崩溃。 这意味着你无法预测会发生什么。

在这种情况下,崩溃很可能,但根本无法保证。

“未定义的行为”并不意味着您将获得段错误,这意味着您可能会遇到段错误。 符合标准的实现也可能决定显示小狗的ASCII艺术。

您可能希望使用Valgrind之类的工具来检查此代码。

  1. 如果访问未初始化的内存,则不会总是出现分段错误。

  2. 你可以在这里访问未初始化的内存。

我得到了一个没有优化的段错误,但是当用优化编译时,gcc根本不打扰s ,它被作为死代码消除了。

gcc -Os -S:

 .cfi_startproc subq $8, %rsp .cfi_def_cfa_offset 16 movl $.LC0, %edi # .LC0 is where "test" is at call strdup addq $8, %rsp .cfi_def_cfa_offset 8 movq %rax, %rdi jmp puts .cfi_endproc 

gcc -S -O(相同于-O2,-O3):

 .LFB23: .cfi_startproc subq $8, %rsp .cfi_def_cfa_offset 16 movl $5, %edi call malloc movq %rax, %rdi testq %rax, %rax je .L2 movl $1953719668, (%rax) movb $0, 4(%rax) .L2: call puts addq $8, %rsp .cfi_def_cfa_offset 8 ret .cfi_endproc