程序b.c中并没有写f1、f2和printf函数,这些函数的代码同样是在连接的时候加入的。
b.exe中有f3的代码,因为f3和f1、f2一起被加入了cs.lib中,而cs.lib被连接入了b.exe,所以b.exe含有它的全部函数,只是main函数中只调用了f1、f2、printf函数而已。
函数f3的代码紧接着函数f2的代码,地址为1056.
那么有没有一种方案,使得在编译连接时能够动态地装入函数的代码,而不是将库函数全部装入exe文件呢?
我们看题目要求的是f.c中的三个函数要装入cs.lib,在编译连接时动态载入代码。但是如果我们用tcc原来的连接方式,就会把cs.lib整个载入代码中。那应该怎么样才不会出现这种情况呢?我觉得应该是改变tlink的连接方式,查看tlink连接选项:
我用tcc将b.c编译成obj文件,再用tlink b.obj/n进行连接,结果出现如下错误:
很显然是没有连接cs.lib所致,但是为什么先用tcc编译再用tlink连接会出错呢?
经过查找资料和实验,tlink连接obj文件生成exe文件的正确指令如下:
第一个意思是用小模式连接b.obj,第二个是指生成的目标文件是b.exe,第三个是指没有使用到映像文件,第四个是指连接需要用到的库文件有cs.lib、emu.lib、maths.lib。
函数f3包含在f.obj里,而后者被载入了cs.lib文件,cs.lib在连接时被载入b.exe文件,那么是不是cs.lib里的所有函数都载入了b.exe文件呢?查找资料有这么一段话:
不会。当启动连接程序时,它会寻找“未定义的外部函数”,也就是说,它将在每一个库文件中查找源代码文件中未定义的函数。当它找到一个未定义的外部函数后,它会引入包含该函数定义的目标代码(obj)。不幸的是,如果这个函数是在一个包含其它函数定义的源文件中被编译的话,那么这些函数也会被包含进来,你的可执行代码中将包含一些不需要的代码。因此,将库函数放到各自的源文件中是很重要的——否则会浪费宝贵的程序空间。有些编译程序包含特殊的“精明的”连接程序,这些连接程序能查出不需要的函数并去掉它们,从而使这些函数不再进入你的程序。