我一直在通過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