前言

        最近发现,自己在电脑之中做了好多技术笔记,但这些关于自己的总结仅限于在自己电脑中,没有与其他人分享交流(虽然也上传到百度文库中),这其实对于做IT的很不好,应该多于别人交流分享,不仅有助于发现自己对某些知识理解上的一些不足和缺陷,还有助于提高沟通交流能力,而且有时你会发现会有意外收获的哦!

        其实很早就开通了博客,之前也写过一些博客,但好久没有写过博客了,于是就想利用博客,把自己以前写过的笔记整理一下,跟大家分享一下,共同交流学习,笔记中有什么错误或者不足的地方,希望大家能够提出宝贵的意见和建议。

        今天是8月31号,明天就是9月1号了,新生也要开学了,新的一学期又要来了,2014也过去了三分之二,那就从第一篇技术博客开始,迎接一个更好的9月!也为了一个更好的2014!加油!


第一篇技术博客本来也在犹豫,到底发哪个方面的内容,本来打算将《Head First设计模式》笔记整理一下的,但是那本书的笔记大部分内容是总结性的东西,如果你没有看过那本书,笔记里的很多东西暂时还不能体会到,所以就选择了C++的笔记,就从还比较实用的动态链接库开始吧!


动态链接库简介

[2]P701

wKioL1QCpBrhcC-TAAVoLrkazHA482.jpg


静态库和动态库

注意:

         .lib库不是静态库,只是一个引入文件,编译链接形成可执行文件的时候,就需要这个文件

         .LIB库才是真正的静态库

[2]P702

wKiom1QCowPSa21DAAOW_KJSXbY953.jpg

wKiom1QCowPDIG76AAO0J_GlGOk095.jpg

编译链接的时候,只要引入库文件.lib只有在运行的时候,才会去加载DLL

引入库文件.lib并不包含实际的代码,只是为链接程序提供必要的信息,以便在可执行文件中建立动态链接时需要用到的重定位表。

使用动态链接库的好处

wKioL1QCpBrBJnGAAAb8Fkd0ziA416.jpg

wKiom1QCowTih0OnAAep1O9IULQ806.jpg

wKioL1QCpBuzRLOgAAJ4ugsweZA857.jpg

wKiom1QCowTTSkRLAAI_svcWDc4073.jpg



一个DLL在内存中只有一个实例

DLL与进程、线程之间的关系

DLL模块被映射到调用它的进程的虚拟地址空间。

DLL使用的内存从调用进程的虚拟地址空间分配,只能被该进程的线程所访问。

DLL的句柄可以被调用进程使用;调用进程的句柄可以被DLL使用。

DLLDLL可以有自己的数据段,但没有自己的堆栈,使用调用进程的栈,与调用它的应用程序相同的堆栈模式。

2)、关于共享数据段

DLL定义的全局变量可以被调用进程访问;DLL可以访问调用进程的全局数据。使用同一DLL的每一个进程都有自己的DLL全局变量实例。如果多个线程并发访问同一变量,则需要使用同步机制;对一个DLL的变量,如果希望每个使用DLL的线程都有自己的值,则应该使用线程局部存储(TLSThread Local Strorage)

 

DLL库的搜索路径

C/C++/C#搜索动态库的时候,都是按照这个顺序来

[2]P710


wKioL1QCpBzRgFfZAASwk82B3ZQ659.jpg



当一个DLL库有依赖库的时候,需要将依赖库也加载进来。

有上面可知,当一个程序内存超过4G时,程序就会挂掉。为什么科大项目,内存泄露4G后,就挂掉了。

如果在一个目录中找到了DLL,那么下面的搜索路径就不会找了。

 

加载方式有两种

1、显式链接

2、隐式链接

这一部分内容,在后面的博客中会有详细的说明。

DllMain函数

[2]P729

wKiom1QCowXSW6QnAAKdeL8-_FQ964.jpg

wKioL1QCpB2zObYjAAUdvWmleWQ039.jpg

wKioL1QCpB7SQnmcAALurGmHAqQ343.jpg


导出和导入函数

DLL文件中分为导出和导入函数

如果想要访问某个DLL中的函数,那么该函数必须是已经被导出的函数

可以使用PE Explorer查看

wKiom1QCowawYGtiAAFzAsDBcGo722.jpg

wKioL1QCpB6R3oTkAANhyxruiho467.jpg

wKiom1QCowfi2XEuAAFNKt4wUgA833.jpg

关于C++编译器函数名处理

详见调用约定,关于调用约定的内容,后面博客中也会有详细论述

查看C++DLL中导出的函数

wKioL1QCpB7Ds8LhAACvYfAjKSQ647.jpg

[2]P707

上图中我们可以看出,函数名比较奇怪,那是因为,C++支持重载,对于重载的多个函数来说,其函数名都是一样的,为了加以区分,在编译链接时,C++会按照自己的规则修改函数的名称,这一过程称为名字改编”(也就是调用约定中函数修饰名的问题),有的书也称为名字粉碎不同的C++编译器会采用不同的规则进行名字改编,这样的话,不同的C++编译器生成的程序在调用对方提供的函数时,可能会出现问题。这个时候,就需要采用我们下面的extern “C”的方式了.



注:

    1、博客中: [1]P22代表参考文献122页,[2]P69代表参考文献269

在所有的技术博客中,都采用这种标注格式

        2、之所以列出参考文献,主要是方便大家查看出处,有什么疑惑的,可以去文献中查看。也方便自己以后复习的查阅。

        3、从word中不能直接粘贴图片到博客中,图片都是一个个的上传到博客中,很麻烦,有知道怎么从word直接复制图片到博客的朋友,留言回复一下,非常感谢!



参考文献

1、《C++ Primer(4 特别版)

2、《VC++深入详解》孙鑫