2016-09-26 35 views
0

我正在嘗試使用extern和各種鏈接方法來更好地理解鏈接過程。將兩個目標文件鏈接在一起會導致分段錯誤11

我有三個文件:

foo.c的:

#include "foo.h" 
int a = 4; 

test.c的:

#include <stdio.h> 

#include "foo.h" 
int main(int, char**); 
int mymain(); 

int mymain() { 
    main(0, 0); 
    printf("test\r\n"); 
    return 0; 
} 
int main(int argc, char** argv) { 
    printf("extern a has %d\r\n", a); 
    return 0; 
} 

了foo.h:

extern int a; // defined in foo.c 

如果我像這樣使用GCC構建每個文件一起鏈接在編譯時:

gcc *.c -o final.bin 

我可以爲執行final.bin:

./final.bin 

並獲得預期的輸出

extern a has 4 

但是,如果我分別編譯(但不鏈接)test.c和foo.c,然後嘗試將目標文件鏈接在一起運行時產生一個二進制文件,我得到了一個分段錯誤11(從我可以收集的是一些通用的內存損壞錯誤,如正常的段錯誤(?)

這是我用來編譯和鏈接分開的生成文件。請注意,我指定我自己的入口點和鏈接對libc中獲得的printf()...

all: test.o foo.o 
    @echo "Making all..." 
    ld test.o foo.o -o together.bin -lc -e _mymain 

test.o: test.c 
    @echo "Making test..." 
    gcc -c test.c -o test.o 

foo.o: foo.c 
    @echo "Making foo..." 
    gcc -c foo.c -o foo.o 

輸出運行 'together.bin' 時:

./together.bin 
extern a has 4 
test 
Segmentation fault: 11 

也許我對「mymain函數簽名' 是錯的?我的猜測是我的'myentry'用法有些問題。另外,如果任何人有任何關於連接器和裝載機如何工作的好書的建議,我當然是在一個市場上。我聽說過有關「連接器和裝載器」的各種各樣的事情,所以我在等待更多意見之前,特別是在我的書中投入時間。

感謝您對此提供的任何幫助...我對連接器的理解不足爲奇。

+0

構建程序的這兩種方式在「將目標文件鏈接在一起」與「將源文件鏈接在一起」方面有很多不同之處! – immibis

+2

'-e'鏈接器選項指向的函數比標準C'main'更具責任。入口點通常由C運行時鏈接,它負責設置和拆除可執行文件的支持結構,並與動態鏈接器緊密結合。你可能會在ld.so的某個地方崩潰,因爲它希望某些結構可以通過關閉來存在。您可以使用gdb驗證並檢查堆棧跟蹤。 – zneak

回答

0

除非你有一個很好的理由這樣做,只是用gcc鏈接:

$ gcc test.o foo.o "-Wl,-e,_mymain" -o ./final.bin; ./final.bin 
extern a has 4 
test 

海合會呼籲LD ---雖然,有一些更多的參數比你在你的例子提供。如果您想確切知道gcc如何調用ld,請使用-v選項。例如:

$ gcc -v test.o foo.o "-Wl,-e,_mymain" -o ./final.bin 
Apple LLVM version 8.0.0 (clang-800.0.38) 
Target: x86_64-apple-darwin15.6.0 
Thread model: posix 
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin 
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o ./final.bin test.o foo.o -e _mymain -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin/libclang_rt.osx.a 
+0

感謝您的回覆 - 這解決了我的問題。我假設gcc以某種方式調用鏈接器...我想知道爲什麼。當我有機會的時候,我會更多地閱讀連接器。我會接受你的解決方案作爲答案,但我不到15個代表,所以我不能這樣做。 – waterproofpatch