我一直在通过Zed Shaw的教程学习C,并在this exercise上遇到了一些问题。代码如下通过不同的编译器进行命令行解析的不同segfaults
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
while(i < argc) {
printf("arg %d: %s\n", i, argv[i]);
i++;
}
// section removed for brevity
return 0;
}
我使用Windows,不喜欢virtualboxing所以我在Cygwin中已经运行的麻烦
。我有两个编译器,一个是Cygwin附带的gcc,另一个是mingw附带的版本(gcc),所以我可以使用DrMemory。
我把文件(名为ex11.c)这样
# Makefile
ex11: ex11.c
gcc -o ex11.exe ex11.c
i686-pc-mingw32-gcc.exe -static-libgcc -static-libstdc++ -ggdb -o ex11b.exe ex11.c
# Command Line
>>> make ex11
...
etc
对于第二个我here的命令。
$ gcc --version
gcc.exe (rubenvb-4.6.3) 4.6.3)
$ i686-pc-mingw32-gcc --version
i686-pc-mingw32-gcc (GCC) 4.7.3
后来,当我运行它们(./ex11
和./ex11b
)我得到的问题。运行正常版本(没有b)没有命令行参数给我一个段错误。带参数运行给了我这样的输出:
$ ./ex11 a
arg 0: a
arg 1: a
运行MinGW的版本(含B)我有没有命令行参数没有问题:
$ ./ex11b
arg 0: (null)
但随后运行一个命令行参数相同( $ ./ex11b a
)segfaults我。第一
.file "ex11.c"
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "arg %d: %s\12\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
subq $48, %rsp
.seh_stackalloc 48
.seh_setframe %rbp, 48
.seh_endprologue
movl %ecx, 16(%rbp)
movq %rdx, 24(%rbp)
call __main
movl $0, -4(%rbp)
jmp .L2
.L3:
movq 24(%rbp), %rax
addq $72, %rax
movq (%rax), %rcx
leaq .LC0(%rip), %rax
movl -4(%rbp), %edx
movq %rcx, %r8
movq %rax, %rcx
call printf
addl $1, -4(%rbp)
.L2:
movl -4(%rbp), %eax
cmpl 16(%rbp), %eax
jl .L3
movl $0, %eax
addq $48, %rsp
popq %rbp
ret
.seh_endproc
.def printf; .scl 2; .type 32; .endef
第二
.file "ex11.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "arg %d: %s\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $0, 28(%esp)
jmp L2
L3:
movl 12(%ebp), %eax
addl $36, %eax
movl (%eax), %eax
movl %eax, 8(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
addl $1, 28(%esp)
L2:
movl 28(%esp), %eax
cmpl 8(%ebp), %eax
jl L3
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE6:
.def _printf; .scl 2; .type 32; .endef
我知道是什么原因导致了段错误的汇编输出的
汇编输出,我想。我有i
初始化为0,所以我有时试图得到一个空值,哪一个不喜欢。我想知道的是这些编译器的不同之处在于它们会像这样打破。
我也很好奇在i=0
我从来没有见过这样的行为。哪些版本的gcc正在使用(在编译器可执行文件名后面添加'--version')?另外,请使用'i686-pc-mingw32-gcc.exe'; 'i686-pc-mingw32-g ++。exe'是C++的前端。 – 2014-09-04 20:49:02
另一个有用的位是汇编器输出。添加'-S'会将它输出到你指定的任何文件中作为'-o'选项的参数。 – 2014-09-04 20:59:09
@ChronoKitsune完成后,看到更新的问题 – Dannnno 2014-09-05 16:07:15