什么是lib文件? lib和dll的关系怎么样? 2008-04-1819:44:37。
)1)编译时需要lib,运行时需要dll。
有lib就足够完成源代码的编译了。
如果要让动态连接的程序也运行,有dll就足够了。
在开发和调试阶段,当然最好一切都有。
)2)典型的动态库程序包括lib和dll文件。 lib文件必须在编译时连接到APP应用程序,但dll文件将在运行时调用。 如果存在dll文件,则对应的lib文件一般是一些索引信息,并且特定实现在dll文件中。 如果只有lib文件,则此lib文件是静态编译的,包含索引和实现。 静态编译的lib文件有一个优点。 安装用户时不需要挂动态库。 但是,还有一个缺点,就是APP比较大,动态库失去了灵活性,升级时必须同时发布新的APP应用程序。
)3)对于动态库,有两个文件。 一个是库).LIB )文件的输入,另一个是DLL文件。 导入库文件包含由DLL导出的函数的名称和位置,而DLL包含实际函数和数据。 由于APP应用程序使用LIB文件链接到所需的DLL文件,并且不会将库中的函数和数据复制到可执行文件中,因此APP应用程序可执行文件必须具有以DLL调用的函数的存储器地址,而不是调用的函数代码这样,当执行一个或多个APP应用程序时,程序代码和调用的函数代码就会链接在一起,从而节省内存资源。 从上面的说明中可以看出,DLL和. LIB文件必须与APP应用程序一起发布。 如果不发出,APP应用程序将出现错误。
一.开发和使用dll需要注意三类文件
1、dll头文件
这是dll中描述输出的类或元件的原型或数据结构的. h文件。 当其他APP应用程序调用dll时,必须将该文件包含在APP应用程序的源文件中。
2、dll部署库文件
这是dll编译、链接成功后生成的文件。 主要作用是当其他APP应用程序调用dll时,必须将该文件引入到APP应用程序中。 否则,无法部署dll。
3、dll文件(.dll )。
这是APP应用程序调用dll运行时的真正可执行文件。 dll APP应用程序将被编译并链接,然后包含. dll文件。 发行时,成功开发的APP应用程序需要. exe和. dll文件,而不需要. lib和dll头文件。
动态链接库(DLL )是作为共享函数库的可执行文件。 通过动态链接,进程可以调用不属于可执行代码的函数。 函数的可执行代码位于包含一个或多个函数的DLL中,这些函数被编译、链接并与使用它们的进程分开存储。 DLL还有助于共享数据和资源。 多个APP应用程序可以同时访问内存中单个DLL副本的内容。
动态链接和静态链接的区别在于,使用动态链接时,可执行文件. dll或. exe只包含在运行时查找dll函数的可执行代码所需的信息。 在静态链接中,链接器获取从静态链接库引用的所有函数,并将库与代码一起放置在可执行文件中。
用动态链接代替静态链接有几个优点。 DLL提供了一种节省内存、减少交换操作、节省磁盘空间、便于升级、提供售后服务、扩展MFC库类的机制,支持多语言程序,并便于创建国际版本
lib和dll文件最大的区别是调用
dll可以陷入静态
lib和DLL
从本章开始,我要说的内容是特定于windows平台的。 其实这篇文章也可以看作是我在windows上开发经验的总结。 因为我现在决定搬到unix。
上一章谈到编译和链接,简单地说了,其实应该总结在这一章里说。 很多只有C的书其实只是学派,对于实际的工作环境,几百个源文件是如何合并的,几乎没有提到。 我让读者一步一步地看看lib和DLL怎么样了。
是最简单的c程序,只需要一个源文件。 此源文件包含以下语句
intmain () {return0; }
当然,这个程序什么也不做。
当程序需要做某件事时,向源文件中添加语句。 例如,开始向main函数添加代码。
#includestdio.h
intmain () )
{
打印(hello world! n ';
返回0;
}
由于人类智力水平的限制,如果一个函数含有很多语句,就不太容易被理解了。 此时,需要子函数。
#includestdio.h
voidShowHello ()
{
打印(hello world! n ';
}
int main () )
{
ShowHello (;
返回0;
}
同样,一个源文件中包含很多函数,很难理解,人们开始分成多个源文件
//main.cpp
void ShowHello (; //[1]
int main () )
{
ShowHello (;
返回0;
}
//hello.cpp
#include stdio.h
void ShowHello ()
{
打印
f("Hello World!n");有了这些知识,你可以开始写一些简单的DLL的应用,但是我可以百分之百的肯定,你会遇到崩溃,而之前的非DLL的版本则没有问题。假如你通过显式加载来使用DLL,有可能会是调用约定不一致而引起崩溃,所谓调用约定就是函数声明前面加上__stdcall __cdecl等等限定词,注意一些宏如WINAPI会定义成这些限定词之一,不理解他们没关系,但是记住一定要保持一致,即声明和定义时一致,这在用隐式加载时不成问题,但是显示加载由于没有利用头文件,就有可能产生不一致。
调用约定并不是我真正要说的,虽然它是一种可能。我要说的是内存分配与释放的问题。请看下面代码:
void foo(string& str)
{
str = "hello";
}
int main()
{
string str;
foo(str);
printf("%sn", str.c_str());
return 0;
}
当函数foo和main在同一个工程中,或者foo在静态库中时,不会有问题,但是如果foo是一个DLL的导出函数时,请不要这么写,它有可能会导致崩溃[6]。崩溃的原因在于“一个模块中分配的内存在另一个模块中释放”,DLL与EXE分属两个模块,例子中foo里面赋值操作导致了内存分配,而main中return语句之后,string对象析构引起内存释放。
我不想穷举全部的这类情况,只请大家在设计DLL接口时考虑清楚内存的分配释放问题,请遵循谁分配,谁释放的原则来进行。
如果不知道该怎么设计,请抄袭我们常见的DLL接口--微软的API的做法,如:
CreateDC
ReleaseDC
的成对调用,一个函数分配了内存,另外一个函数用来释放内存。
回到我们有可能崩溃的例子中来,怎么修改才能避免呢?
这可以做为一个练习让读者来做,这个练习用的时间也许会比较长,如果你做好了,那么你差不多就出师了。一时想不到也不用急,我至少见过两个有五年以上经验的程序员依然犯这样的错误。
注[1]:为了说明的需要,我这里使用直接声明的方式,实际工程中是应该使用头文件的。
注[2]: 还有线程创建与销毁也会路过DLL的入口,但是这对新手来说意义不大。
注[3]:DEF文件格式很简单,关于DEF文件的例子,可以通过新建一个ATL COM工程看到。
注[4]:第一种方法和使用静态库差不多,包含头文件,链接库文件,然后就像是使用普通函数一样,称为隐式加载。
注[5]:具体调用方法请参阅MSDN。
注[6]:之所以说有可能是因为,如果两个工程的设置都是采用动态连接到运行库,那么分配释放其实都在运行库的DLL中进行,那么这种情况便不会发生崩溃
1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除。
2.未经原作者允许不得转载本文内容,否则将视为侵权;
3.转载或者引用本文内容请注明来源及原作者;
4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。
下面是我的个人微信公众号,关注【一个早起的程序员】精彩系列文章每天不断。
版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。