当我们编译包含'main'而没有链接的源代码时,为什么我们不能运行它?

yoy*_*fun 1 c c++ ubuntu gcc compilation

我正在学习编译过程,我知道链接主要用于链接包含'main'函数的二进制文件和包含在我们的主函数中使用的其他辅助函数的其他二进制文件.

但是,当我尝试使用代码运行目标文件时:

int main() {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在Ubuntu上使用gcc中的-c命令编译,我尝试运行它并得到错误:

"bash:./ source.o:无法执行二进制文件:exec格式错误"

Bas*_*tch 6

阅读Levine的连接器和装载器.

了解ELF.

试着用编译gcc -v(你会看到什么实际使用的方案:cc1编译 C代码到一些汇编,as组装到这部分对象文件,ldcollect2链接).另请参阅生成的汇编程序文件gcc -S -fverbose-asm -O.请注意,gcc了解(并特别编译)该main函数.并且可执行文件的起点由一些crt0等提供(它不是 main一些_start常规编码的汇编程序,它会调用你的main....).

对象文件可执行文件不同.可执行文件包含诸如crt0C标准库之类的东西,或者某种方式它作为共享对象动态链接(并且你需要将你的source.o-compiled从空的mainin source.c- 链接到可执行文件中).

在Linux上,使用objdump(1)readelf(1)(在一些现有的二进制文件上,也在你的source.o目标文件上)

另请参阅elf(5),execve(2),ld-linux(8),Linux程序集,系统调用(2),高级Linux编程,操作系统:三个简单的部分,以及(了解libc.so)Drepper的如何编写共享图书馆,龙书 ......

(你需要阅读整本书才能理解细节;我提供了一些参考资料)

另请参阅 Common Lisp和SBCL.它的编译器有一个非常不同的模型(与C完全不同).