程序装载及静态动态链接

程序装载

程序执行的过程是 编译-汇编-链接成可执行文件–通过装载器把可以执行文件装载到内存中,cpu从内存中读取装载器装入的指令和数据。

装载器把指令和数据装载到内存需要满足两个要求:

  • 可执行程序加载后占用的内存空间是连续的。执行指令的时候是一条一条指令的执行
  • 不能让程序自身决定他在内存中加载的位置,因为如果有很多程序执行的话,那么程序本身不知道那个内存地址是否已经被占用了。
    为了满足这些条件(因为有的程序想要实现上面的功能,那系统就假装能让他们实现),系统用了一个办法,在物理地址空间中找到了一块连续的内存,分配给程序,然后把这段物理地址和程序里需要的地址做一个映射。 这就是虚拟地址空间物理地址空间

内存分段

找出一块物理内存和虚拟内存进行映射的方法叫做分段。但是分段会产生内存碎片
比如1GB内存分配了512MB 128MB 256MB 128MB的内存,这时候两个128MB的资源释放了,但是这两个内存不是连续的如果遇到一个需要129MB内存的程序就无法加载进来。

处理办法用了内存交换
用了交换区来作为中介,把256MB的程序先放入交换区,然后再加载回来,把碎片空间连接在一起。

内存分页

内存分段虽然解决了内存碎片的问题,但是每次内存交换非常耗时。
现在计算机的内存管理里面常用内存分页

分页的思想就是把原来一大段的内存,细分下去,分成固定长度的一小段一小段。之后虚拟内存到物理内存的映射也根据分页来做了。

静态链接和动态链接

当系统启动时,可能有非常多的程序需要通过装载器把数据和代码装载到内存中,而且又很多程序会用到相同的数据和代码,如果每次都装载那非常消耗内存。因此就需要用链接的方式来达到代码的复用。

静态链接库

链接器从静态链接库LIB获取所有被引用函数,并将库同代码一起放到可执行文件中,应该就是编译的时候就把所有的信息都加入。 就是非常消耗内存的方式。

  • 需要的文件: 头文件 .h 、静态库 .lib
  • 头文件.h中有函数的声明,使用静态链接库的项目需要引用该文件才能编译通过
  • .lib包含了实际执行代码、符号表等等
  • 加载lib的方法:  法1.使用编译链接参数或者VS的配置属性来设置    法2.使用pragma编译语句,例如pragma comment(lib,“a.lib”)
  • .lib中的指令将全部被直接包含在最终生成的 EXE 文件中
动态链接库

允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位DLL中函数的可执行代码所需的信息。
动态链接库实现了代码在开发阶段的复用和运行阶段的复用
显式调用动态库步骤:

1、创建一个函数指针,其指针数据类型要与调用的 DLL 引出函数相吻合。
2、通过 Win32 API 函数LoadLibrary()显式的调用DLL,此函数返回DLL 的实例句柄。
3、通过 Win32 API 函数GetProcAddress()获取要调用的DLL 的函数地址,把结果赋给自定义函数的指针类型。
4、使用函数指针来调用 DLL 函数。
5、最后调用完成后,通过 Win32 API 函数FreeLibrary()释放DLL 函数。

内存、堆栈

  • 栈:操作系统自动分配释放,存放函数值、局部变量的值,维护函数调用上下文;编译器在编译的时候就会把一些数据放到栈中。

常称为堆栈帧或者活动记录,一般包含:
函数返回地址和参数
临时变量:包含函数非静态局部变量和编译器生成的临时变量等
保留上下文:包括函数前后调用需要保持不变的寄存器

  • 堆:一般由程序员分配释放,如果程序员不释放可能程序结束会主动释放,也有可能就是内存泄漏。

分配算法:空闲链表 位图 对象池

  • 可执行文件映像:存储着可执行文件在内存中的映像,由装载器装载是将可执行文件的内存读取或映射到这里

  • 保留区:保留区并不是一个单一的内存区域,而是对内存中受到保护而禁止访问的内存区域的总称,如通常 C 语言讲无效指针赋值为 0(NULL),因此 0 地址正常情况下不可能有效的访问数据

  • 段错误 segment fault
    用一个指针指向一个不允许读写的内存地址,而程序尝试用这个指针来读写就会出现这个错误.
    将指针初始化为 NULL,之后没有给它一个合理的值就开始使用指针
    没用初始化栈中的指针,指针的值一般会是随机数,之后就直接开始使用指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值