这是c代码:
char **s;
s[334]=strdup("test");
printf("%s\n",s[334]);`
我知道strdup会分配“test”,但是我们将把指针放到字符串“test”的情况下[334]没有分配,但是,这段代码就像魅力一样
答案 0 :(得分:5)
您的代码显示未定义的行为。那不意味着它会崩溃。这意味着你无法预测会发生什么。
崩溃很可能,但在这种情况下根本不能保证。
答案 1 :(得分:3)
如果访问未初始化的内存,则不会总是出现分段错误。
您可以在此处访问未初始化的内存。
答案 2 :(得分:3)
“未定义的行为”并不意味着您将获得段错误,这意味着您可能会遇到段错误。符合标准的实现也可能决定显示小狗的ASCII艺术。
您可能希望使用Valgrind等工具检查此代码。
答案 3 :(得分: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
答案 4 :(得分:2)
编译器对我们来说太聪明了!它知道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"));
因此,偶然发生了段故障(此时)。