函数/代码安全、malloc的低层实现

般说到代码安全时,一般会涉及这几个方面:
一、函数中的指针操作出现下面几种情况:
1.指针访问无效的内存
2指针所指资源没释放,导致内存空间越占越大。
3.指针已释放资源,又去访问。
二、函数在结束的时候,返回局部变量的地址或引用。
三、代码的线程安全。


  • 如何知道代码或函数是线程安全的?

在函数运行的过程中,可能同一个会导致两个或两个以上的线程来访问变量,那么,如果在时间上出现你先取,我在你还没使用结束的情况下就取值,会导致最终的结果不是我们所要的结果。也就是说“运行程序的结果,随着线程调度的顺序的不同,而出现不同的运行结果。”我们把这种结果称之为程序代码出现了竞态条件,把发生竞态条件的代码段,称为临界区代码段。对于临界区代码段,需要保证它为原子操作,为了保证临界区代码段的原子操作,需要对临界区代码段加互斥锁进行控制。


关键字“volatile”的作用:
在多线程环境中,不允许将其修饰的变量放入到eche缓存中,所有线程读写的都是内存数据段的变量。
这里写图片描述
图中,将a和b取data这句代码翻译成了三句汇编码,对b取data时,是直接从缓存器eax中取得,这样就增加了代码运行效率,但另外也引出了另外一个问题–如果运算器对缓存器中的值发生更改,而系统又没能及时的将更改后的值刷回到内存地址中去,那么,另外的线程访问data时,会访问到旧的数据,导致程序运算结果发生错误。
此时,给data加了“volatile”关键字,编译器会将函数中的两句代码翻译成下图的形式。
这里写图片描述
b的取值也是从地址中进行取值,一旦对data变量发生修改,那么修改结果会直接保存到内存地址中去。


malloc函数的底层实现:

malloc函数的实现是用户通过调用API来访问核函数,核函数为系统自己提供。
malloc在分配内存时,以128k为界限,大于128k,使用do_mmap函数进行内存分配,小于128k,使用do_brk函数进行内存分配,这里通过break指针的移动来分配内存。

堆区的内存结构如下:
这里写图片描述
堆区主要由三部分组成:堆的开始部分(start_brk),堆顶(break),堆的最大限制(rlimit)。从start_brk到break部分,是系统为用户映射好的虚拟地址,可供用户访问,从break往上为未映射的地址空间,用户不可访问,否则会发生段错误“内存非法访问”。

堆的系统调用,主要通过brk,mmap,unmmap这些系统调用完成。
以一个具体例子来说明内存分配原理;
这里写图片描述
情况1.内存分配小于128K时。
1. 图1.当堆区未分配内存时,break和start_brk指向同一个地方,它们都指向数据段的最高地址。
2. 当调用A=malloc(10K)后,系统会自动调用brk()函数,将break指针向下移动10K。
但这里有一个特殊情况:break+10K之后,完成了虚拟内存分配,但并没有物理页与之对应,所以当进程执行到这一块之后,发生缺页中断,这时候,系统才为这块内存分配物理页,如果这块内存分配后却从来不用,那么系统不会为这块区域分配实际内存。
3.调用b=malloc(20k)之后,得到图3操作。
情况2.malloc分配内存大于128K时
这里写图片描述
4.当系统调用e=malloc(200K),malloc分配空间大于128K时,系统调用mmap函数,在堆区和栈区之间为用户分配一块虚拟内存,这样做原因有一下两点:
mmap函数分配的内存可以单独释放,brk函数分配的内存必须要等到break所指向的内存释放之后才可以释放。
5.调用c=malloc(100K)时,如图5.
6.调用free(e),时,e所对应的虚拟地址和物理地址一起释放。如图6
这里写图片描述
7.free(b),图7,此时,只有一个break指针指向堆顶,如果回退,c这块的内存就无法进行管理了, 所以break指针不变。系统上将b视为已经收回的内存,如果再需要分配20K大小的内存时,就有可能将b这块内存分配出去。
8.free(c),此时b和c加起来的内存为120K,还不足128K,所以break不执行收缩这个动作,如果break所指向的最高地址空间的空闲内存大于128K,则执行一个收缩操作,其效果如图9。
这里借鉴了博客malloc的低层实现的过程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值