【发布时间】:2017-02-03 06:33:34
【问题描述】:
我正在试验外部变量和各种链接方法,以更好地理解链接过程。
我有三个文件:
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(从我可以收集一些通用的内存损坏错误,例如正常的段错误(?)
这是我用来分别编译和链接的makefile。注意我正在指定我自己的入口点并链接到 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”用法有问题。
另外,如果有人对链接器和加载器如何工作的好书有任何建议,我当然在市场上想要一本。我听说过关于“链接器和加载器”的各种说法,所以我正在等待更多的意见,然后再特别投入时间阅读那本书。
感谢您对此提供的任何帮助...我对链接器的理解至少可以说是低于标准的。
【问题讨论】:
-
这两种构建程序的方式比“将目标文件链接在一起”与“将源文件链接在一起”有更多的区别!
-
-e链接器选项指向的函数比标准的 Cmain具有更多的职责。入口点通常从 C 运行时链接进来,它负责为可执行文件设置和拆除支持结构,与动态链接器紧密耦合。您可能在 ld.so 的某个地方崩溃了,因为它预计某些结构会在关闭时存在。您可以使用 gdb 验证并检查堆栈跟踪。
标签: c linker segmentation-fault extern