编译过程的一些小知识——LIB与DLL的区别

转载 2012年03月31日 09:31:35

相信很多人都用过VC6.0与Visual Studio系列产品。

也有很多牛B人士用它们创造过很人的神话,铸就许多美丽的传说。

那你们知道为何你能用它创始出那么多的奇迹,这是你一个人的成功?

你是否关心过你是如何能动态的链接它给你提供的内库,它是如何控制你的IO流的?

为何C++的语法是这么规定的,它又是如何实现这些语法的呢?

本文和接下来的文章很肤浅的介绍了这些东西,让基本上还在一个.cpp和.h文件中写出超然代码的人也能够了看到一些往往忽略的东西。

Author:lostName

Time:2010-4-16

Version:v1.1

Run:VC6.0与VS2008

首先我们来明白一个工程从创建到可执行文件的过程:

创建工程——编写代码——编译——链接——可执行文件。

下一篇日记中会重点介绍VC的编译与链接的过程,此文重点在讲项目、dll与lib

我相信任何人肯定能从VC6.0的目录下找到两个文件夹lib与include。而include内的都是大家熟悉的头文件(如iostream.h、conio.h)等文件。这些头文大家都是能够查看与打开的,就好比你写的头文件一样,里面有很多的声明。而且我敢肯定的是大家肯定找不到的是.cpp文件。你也许会好奇光有头文件里这些类这些声明,而没有具体的实现的话(c++一般都是在.h中写类的一些接口,而实现的部分是在.cpp文件中),我们是如何来用它的呢?

这就和你的编译器有很大的关系了。不同的编译器处理的方式不通。就拿VC6.0来说:

假设你有3个.cpp文件(a.cpp、b.cpp、c.pp)。在编译器预处理的时候它会把头文件(.h)的内容都会插入到你的对应的.cpp文件中。如a.cpp文件中有#include <iostream>、#include <a.h>。则预处理的时候会把a.h文件的内容都复制到了a.cpp文件中,当然还有include文件夹下的iostream.h内容,当然iostream.h文件中的<ios.h>,<streamb.h>,<istream.h>,<ostream.h>中的内容也会通过递归的方式加入进来( 当然不是都不是整个.h文件的内容都一定要加入进去的,预处理做的事情不只有这么简单,如想了解可以去查资料,这里只是不必增加复杂度,你暂时可以理解为都加入进去了)。

然后每个.cpp文件其实可以理解为一个编译的单元,可以分别编译的。(这样的做法,很明显可以提高速度,如果你每改一个文件,所以文件都要重新都编译下的话,所耗的时间是相当的惊人的,所以c++把每个编译单元都独立出来编译成obj文件,然后在通过链接成为一个可执行文件。)。通过编译每个cpp文件它会产生一个.obj文件。如上面的三个文件它会产生a.obj,b.obj,c.obj文件(还有一些其他文件,但你不需要了解,你需要记住只是这里说的是VC6.0的编译器)。这里面都是2进制的代码,每个obj文件它所含的内容除了编译后的产生的数据和代码外,它还必须含有3个表:未解决符号表、导出符号表、地址重定向表。

先别着急了解这3个表的含义。我们来通过程序了解:

假设有:

A.cpp:

extern  int m_a;            //声明变量a

void set()

{

    m_a = 6;

}

B.cpp:

int m_a  = 6;                    //全局变量a

void add()

{

    m_a++;

};

编译这两个文件产生了A.obj、B.obj文件。可这些文件是分别编译的,我们怎么知道A.cpp中的值的大小呢?这就是表的作用了!

.obj内除了自己数据外,还有的导入符号表和未解决符号表就是告诉编译器我能提供什么东西,我还需要什么东西。地址重定向表是解决地址冲突的,这里不做深究。如:

A.obj的导出符号表中有m_a、set()。未解决表中没有。

B.obj的导出符号表中有add()。未解决表中有m_a;

这样以后再链接的时候,编译器去找B.obj需要的m_a的时候找到了唯一的A.obj中导出的m_a。(下一章的内部连接和外部连接会更深入的了解)。

这样然后整合到一个.exe(含main方法的那个cpp文件)文件中成为一个可执行文件。

好了现在说完这些,你就会更加清楚的去了解lib与dll内。

lib分为静态的链接库和动态的链接库,这些也都是2进制代码。

(1)我们不是在VC的lib文件夹下看到了很多的lib文件吗?这些是静态的链接库,你其实可以把它理解为一个项目(项文件含有的obj文件的总和,如为完成某个功能,一般不是只需要一个cpp文件就能完成的,而每个cpp在编译后都会产生obj)的obj文件(为方便理解才这么所,当然不可能这么简单)。当然这些就是Microsoft的VC6.0的源文件发布后能提供的东西。所以我们自己编写的代码中的头文件需要的东西,可以对应的lib找到对应的入口。如iostream.h中的iostream(const iostream&)函数需要的东西可以从lib中找到入口,如果某个对应lib里的导出符号表提供了iostream(const iostream&)函数的入口,我们就调用这lib中的iostream(const iostream&)具体实现(lib里的2进制代码)。

(2)而使用动态链接中的lib,不是obj文件的集合,即里面不会有实际的实现,它只是提供动态链接到DLL(后面有说到它)所需要的信息,这种lib可以在编译一个DLL工程时由编译器生成。

所有你写的代码是结合了前人无数的研究与开发的产品,集合了几代人的成就。你好比是用到了他们所写的源码一样,只是你看不到它的源码(.cpp文件)而已。按照我家GY的话来说就是一代一代哟!

(3)dll是动态链接库。区分动态的链接库与静态的链接库很简单,就是静态的链接库是在程序链接的时候就已经链接到exe文件(可执行文件)内了!而动态的链接库是你的exe(可执行文件)运行的时候需要的链接库。也就是说如果你用到了dll的话,那你光有个exe文件没用,想要运行的话必须还要有动态链接库的存在,如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。

如果有dll文件(这就是VS2008的内库了,好比就是C++提供的那些lib一样,它这么做的目的还是为了节省了内存资源,提高时间,后面有说到),那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。

动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,LIB中存放的不是被调用的函数代码,而是 DLL中相应函数代码的地址,从而节省了内存资源。

(4)总之1个静态的lib可以看成是若干个obj的内容(vc6.0安装包的内容)。而动态的lib一般是和dll一起存在的,这时候的LIB中存放的不是被调用的函数代码,而是 DLL中相应函数代码的地址,而DLL是只能在程序运行的时候才能使用的(VS2008的内容)。

如何编译生成dll

动态链接库是Windows的基石。所有的Win32 API函数都包含在DLL中。3个最重要的DLL是KERNEL32.DLL,它由管理内存、进程和线程的函数组成;USER32.DLL,它由执行用户界面...

将C语言源代码编译成动态链接库

下面我们举一个例子,用C语言写一个简单的函数,并在控制台(命令行)中将它编译为DLL。 一、源代码 我们创建一个C语言源程序:Test.c 关键:__declspec(dllex...

如何修改已编译的dll文件

我们平时在工作中经常会遇到一些已经被编译后的DLL,而且更加麻烦是没有源代码可以进行修改,只能针对这个DLL的文件进行修改才能得到我们想要的结果;本文将通过一个实例来演示如果完成一个简单的修改;我们将...

VS编译 Lib库和Dll库的区别

共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library。 一种是LIB...

VS如何创建和使用lib文件

如果你当前正在使用vs写了一个工程,那么你想现在就生成一个Lib文件,那么可以直接在“项目属性”上进行修改i 项目属性-》配置属性-》常规-》配置类型中修改即可,如下图所示。 lib的使用...

编写简单DLL及CL编译链接

NO.1 使用DEF文件: //dllsingle.h #i nclude INT APIENTRY add(int a,int b); //dllsingle.cpp #...
  • thenile
  • thenile
  • 2011年11月08日 08:55
  • 2154

编译过程的一些小知识——内部连接与外部连接

首先,我们来了解下定义: 内部连接:如果一个名称对编译单元(.cpp)来说是局部的,在链接的时候其他的编译单元无法链接到它。 外部连接:如果一个名称对编译单元来说不是局部的,而在链接的时候...

openssl-1.0.0d-static-lib编译过程

openssl-1.0.0d-static-lib编译过程 openssl编译成静态库, 包含进工程的好处是可以避免系统中其他openssl版本的影响. 系统中有很多第三方的程序在使用openssl....

VS添加lib以及对编译过程的总结

本来是想在VS2013添加一个lib的。由此认识到对编译的原理认识不清楚,所以记录一下 先说在vs中添加lib库的方法: 通过设置工程来添加lib库: 1.添加一个项目,右键属性,改变 配置属性-...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:编译过程的一些小知识——LIB与DLL的区别
举报原因:
原因补充:

(最多只允许输入30个字)