obj文件的连接问题以及tlib的基本用法
1、基础研究
用tcc将程序编译为.obj文件。
这里也可以使用tcc -linclude run.c来将run.c文件编译成run.obj文件。
再用tcc对下面的程序进行编译链接,发现提示错误:
提示标志f在程序中未定义。这说明如果程序里出现未定义的变量或函数,编译器能够正常将原文件编译成.obj文件,只是会提示而已。
要怎么生成正确的exe文件呢,我们要把run1.c中未定义的f函数链接进来,但是我们之前的链接都是链接的系统提供的相关文件,怎么链接自带文件呢?我们先研究一下tlib.exe。
tlib.exe使用方法如下;
即使用tlib的格式为tlib libname [/C] [/E] commands, listfile
libname:要建立的用户目标模块库,缺省的扩展名为.LIB
/C:大小写敏感标志。该选项不常用。
/E:建立扩展字典。建立扩展字典可以加速大的库文件的连接过程。
commands: 操作列表,由若干个动作符以及每个动作符后面的文件名或模块名组成。TILB支持的动作符有5种:“+"、“-"、“*"、“-*"或“*-"、“-+"或“+-"。“+"是把指定的文件加到指定的库中; “-"从库中删除指定的模块;“*"将相应的模块从库中抽取并写到指定的文件中,原库不变;“-*"或“*-"是将库中指定的模块拷贝到指定的文件中,然后把该模块从库中删除;“-+"或“+-"是将指定的模块用指定的文件或模块代替。
Listfile:建立列表文件。列表文件按字母顺序将库中各模块列表,为文本文件,可用DOS的TYPE命令查看。
那么将含有f函数的run.obj添加到cs.lib里的语句如下:
之后用tcc编译链接文件run1.c,没有出现错误提示。用debug加载生成的exe文件:
这是main函数的代码
这是f函数的代码
所以,我们将函数f写在程序run.c中,编译成run.obj,再将run.obj用tlib链接入cs.lib,这样tcc编译时发现原文件中没有定义函数f,就会在c语言默认的函数库cs.lib中寻找,找到后将其链接,生成run1.exe文件,所以我们在run1.exe文件中可以看到函数f的代码,它是在tlink连接时加入的。
用tlib cs.lib cs.txt可以在cs.txt或者cs.lst文件中导入cs.lib的函数的目录。
将此程序编译成f.obj,并加入cs.lib中。
将上面的程序编译链接成b.exe,用debug加载:
Main函数的内容为:
f1函数的内容为:
f2函数的内容为:
函数func的内容为;
程序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)。不幸的是,如果这个函数是在一个包含其它函数定义的源文件中被编译的话,那么这些函数也会被包含进来,你的可执行代码中将包含一些不需要的代码。因此,将库函数放到各自的源文件中是很重要的——否则会浪费宝贵的程序空间。有些编译程序包含特殊的“精明的”连接程序,这些连接程序能查出不需要的函数并去掉它们,从而使这些函数不再进入你的程序。
很显然tlink并不是上面资料里所说的“精明的”连接程序,它会将和源代码中未定义函数一起编译的所有函数都载入exe文件中,所以f3会被载入b.exe中。
那么我们的问题就很好解决了,我们可以将f1、f2函数写在一个程序里编译成obj文件,将f3写在一个程序里编译成obj文件,再将这两个文件加入cs.lib中,然后进行下面的连接,b.exe文件中就不会出现f3函数的代码了。实验结果发现,原来紧跟在f2的代码后面的f3的代码现在没有了:
所以其实是我之前的思路重点错了,只觉得函数f1、f2、f3都在cs.lib里面不管怎么放都是一样的,但是其实它们编译的方法不同,在cs.lib里面存放的位置或机制也应该不同,我们思考时,应该更加全面地想问题。
用下面的函数替换cs.lib里的printf函数:
将函数编译成obj文件,再用如下语句替换:
这样再使用printf函数就会输出“Do you want to use printf?No printf here.”
如下图程序:
在正常情况下应该输出3,但是用更改后的cs.lib连接后,输出结果如下:
这时printf函数是一个不接受参数、只输出固定语句的函数。
2、拓展研究
1、我们在本章研究里是把要添加的obj文件插入cs.lib中再连接,那么能否自己建立lib库,并使tcc编译时对它进行连接呢?
2、我们知道cs.lib里在被连接时是将源文件中未被定义的函数及其一起编译的函数全部加入生成的exe文件中,那么cs.lib里的其他文件是怎么编译的?都是单独编译的吗?
3、Printf和put函数有什么区别?
4、obj文件给出的是偏移地址,exe文件给出了段地址和偏移地址?
5、include头文件在预编译过程中把其他文件合成一个文件。尝试#include<f.c>也是可以正确运行的,看汇编代码这种和加入cs.lib有什么不一样。
6、加入obj文件后之后cs.lib的大小减小了,这是为什么?
3、研究总结
本章研究了obj文件的连接问题,掌握了将obj文件加入cs.lib从而连接进文件的方法,熟悉了tlib.exe的基本用法。
obj文件的连接问题以及tlib的基本用法的更多相关文章
- delphi 连接 c++ builder 生成obj文件
delphi 连接 c++ builder 生成obj文件 delphi 可以连接c++ builder 生成OMF格式的obj文件,会报一个错.[DCC Error] E2065 Unsatisfi ...
- 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包
前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”) ...
- OBJ文件
OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模 ...
- 工作总结 1 sql写法 insert into select from 2 vs中 obj文件和bin文件 3 npoi 模板copy CopySheet 最好先全部Copy完后 再根据生成sheet写数据 4 sheet.CopyRow(rowsindex, rowsindex + x); 5 npoi 复制模板如果出现单元格显示问题
我们可以从一个表中复制所有的列插入到另一个已存在的表中: INSERT INTO table2SELECT * FROM table1; 或者我们可以只复制希望的列插入到另一个已存在的表中: INSE ...
- 关于bin和obj文件夹。debug 和release的区别(转)
关于bin和obj文件夹. 楼主hcaihao(影子男孩)2002-05-29 20:04:24 在 .NET技术 / C# 提问 VS.Net会生成bin和obj文件夹以及它们下面的Debug和Re ...
- 记一次C++编程引用obj文件作为静态库文件
简介 常用静态库文件的名字一般是 ***.lib ,例如 nisyscfg.lib 就是一个静态库文件,但是一个例程居然是引用 **.obj 文件作为静态库,有点非常规啊. 这是一个NI488.2 的 ...
- CSharpGL(9)解析OBJ文件并用CSharpGL渲染
CSharpGL(9)解析OBJ文件并用CSharpGL渲染 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo ...
- [计算机图形学] OpenGL读取obj文件并显示其3D效果
读取三维网格模型(Wavefront OBJ文件) 无法向立方体:cube.obj 有法向兔子模型:bunny.obj 有法向有纹理八字模型:Eight.obj OBJ文件的格式可参考:http: ...
- 通过udl文件得到连接字符串
1.新建一个文件,文件名任意,扩展名为udl 2.双击打开这个udl文件 3.点下一步: 4.测试连接成功后点击确定 5.用记事本打开这个udl文件: 连接字符串就出来了
随机推荐
- 自定义AuthorizeAttribute
原文地址:http://www.cnblogs.com/shanyou/archive/2010/03/29/1699511.html 网站的权限判断是一个非常普遍的需求,从文章ASP.NET MVC ...
- Scala 编程(二)类和对象
类,字段和方法 类是对象的蓝图.一旦定义了类,就可以用关键字new从类的蓝图里创建对象,类的定义: class ChecksumAccumulator { // class definition go ...
- openStack 对象存储object storage swift
- 关于FIN_WAIT1
前些天,一堆人在 TCPCopy 社区里闲扯蛋,有人提了一个问题:FIN_WAIT1 能持续多久?引发了一场讨论,期间我得到斌哥和多位朋友的点化,受益良多. 让我们热热身,通过一张旧图来回忆一下 TC ...
- N - 畅通工程再续 - hdu 1875
Description 相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题 ...
- [转] Ubuntu 12.04下LAMP安装配置 (Linux+Apache+Mysql+PHP)
我是一个Linux新手,想要安装一台Ubuntu 12.04版的Linux服务器,用这台服务器上的LAMP套件来运行我自己的个人网站.LAMP套件就是 “Linux+Apache+Mysql+PHP这 ...
- STL之Pairs
什么是Pair 关于类Pair的介绍,下面是引自<C++ Standard Library>的一段话: The class pair is provided to treat two va ...
- lubuntu12.11 source.list
deb http://ports.ubuntu.com/ubuntu-ports/ precise main universe deb-src http://ports.ubuntu.com/ubun ...
- The requested page cannot be accessed because the related configuration data for the page is invalid
当在VS2013下开发web site时,调试时都是在IIS Express中进行的,没有问题.当部署到IIS中,出现:The requested page cannot be accessed be ...
- Mysql group_concat
select p.id,p.parent_id,group_concat(distinct(CONCAT("分类名称:",c.name)) order by c.id desc s ...