以下代码编译并在GCC编译器上运行。
#include <stdio.h>
int arr[10];
int func()
{
printf("In func\n");
return 0;
}
int main()
{
if (&arr[func()])
printf("In main\n");
return 0;
}
输出:
In main
为什么不执行printf("In func\n");
?
答案 0 :(得分:3)
似乎存在一个微妙的问题,无论是有意还是无意的最新gcc的各种组合。关于Archlinux上最新内核4.15.8的ver 7.3。无论出于何种原因,为func()
生成的代码都省略了对main()
的调用。 e.g。
$ gcc -S -masm=intel -o infunc2.asm infunc2.c
生成的程序集是:
$ cat infunc2.asm
.file "infunc2.c"
.intel_syntax noprefix
.text
.comm arr,40,32
.section .rodata
.LC0:
.string "In func"
.text
.globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC0[rip]
call puts@PLT
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.section .rodata
.LC1:
.string "In main"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC1[rip]
call puts@PLT
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 7.3.0"
.section .note.GNU-stack,"",@progbits
请注意,func()
的来电标记为.LFB0:
。尽管main:
中存在func
字符串,.LFB0:
的过程仍然不会调用"In func"
或.LC0:
。我怀疑这不是预期的行为。
例如,没有优化-O0
的简单编译不会调用该函数,例如:
$ gcc -g -O0 -o bin/if2 infunc2.c
$ ./bin/if2
In main
更改代码以存储arr[func()]
的地址会强制调用func()
,例如
#include <stdio.h>
int arr[10];
int func()
{
printf ("In func\n");
return 0;
}
int main (void)
{
int *p = &arr[func()];
if (p)
printf("In main\n");
return 0;
}
然后
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/infunc infunc.c
$ ./bin/infunc
In func
In main
生成的程序集支持不同的行为:
$ gcc -S -masm=intel -o infunc.asm infunc.c
$ cat infunc.asm
.file "infunc.c"
.intel_syntax noprefix
.text
.comm arr,40,32
.section .rodata
.LC0:
.string "In func"
.text
.globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC0[rip]
call puts@PLT
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.section .rodata
.LC1:
.string "In main"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 16
mov eax, 0
call func
cdqe
lea rdx, 0[0+rax*4]
lea rax, arr[rip]
add rax, rdx
mov QWORD PTR -8[rbp], rax
cmp QWORD PTR -8[rbp], 0
je .L4
lea rdi, .LC1[rip]
call puts@PLT
.L4:
mov eax, 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 7.3.0"
.section .note.GNU-stack,"",@progbits
我希望我能为这里的处理提供一些合理的解释,但我只能记录它。似乎我们需要与gcc列表上的人交谈。
内部地址计算中丢弃的副作用&#39;如果&#39;
这似乎是gcc中的一个回归,它将根据个人发行版是否应用足够的补丁来掩盖它而出现。这是工作中的gcc bug。 Bug 84607
答案 1 :(得分:2)
这是一个gcc错误(#84607),已在gcc 7.3.1或更高版本中修复。
答案 2 :(得分:1)
问题在于您的编译。我用gcc编译。我编译了你的文件:
gcc main.c -o prog
./prog
In func
In main
对我来说似乎很好。如果使用与gcc不同的编译器,请检查如何使用编译器进行编译的过程。我也使用gcc 7.3