程序的内存分区

总结来自:拓跋阿秀大佬的面试知识网站,侵权删

一.程序的内存分区/程序模型

        内存分区分别是堆、栈,自由存储区,全局/静态存储区、常量存储区和代码存储区。

 :在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集里面,效率很高,但是分配的内存容量有限(1MB~8MB之间)。

:就是哪些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量和静态变量又分为初始化的和未初始化的,在C++中没有这个区分,它们共占同一块内存区,在该区定义的变量若没有初始化,则会被自动初始化,例如int型变量自动初始化为0。

常量存储区:这是一块比较特殊的存储区,这里面存放的是常量,不允许修改。

代码区:存放函数体的二进制代码。

二.sort()函数中的排序函数是快排还是插入排序?

        sort()源码中采用的是 IntroSort内省式排序的混合式排序算法。

第一步:

  • 首先进行判断排序的元素是否大于 stl_threshould ,stl_thresould是一个常量值是16,意思是说我传入的元素规模小于16的时候直接采用插入排序。
  • (为啥呢?因为插入排序在面对“几近排序”的序列时,表现更好,而快排是通过递归实现的,会为了极小的子序列产生很多的递归调用,在区间长度小的时候经常不如插入排序效率高)

第二步:

  • 如果说我们的元素规模大于16,那就需要判断是不是能采用快速排序,如何判断呢?
  • 快排是使用递归来实现的,如果说我们进行判断我们的递归升读有没有到达递归升读的限制阈值 2*lg(n) ,如果递归深度没到达就使用快速排序。

第三步:

  • 如果说大于我们的最深递归深度阈值的话,这个时候说明快排复杂度退化了(比如很不巧基准元素多次选取到了当前区间中最小或最大的元素,这种情况下,每次划分只能将区间缩小1个元素,造成递归深度过深)
  • 此时采用堆排序,堆排序是可以保证稳定 O(nlogn) 的时间复杂度的。

三.什么是内存泄露,如何检测和避免?

        一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序的运行期决定)内存块,使用完后必须显式释放的内容。应用程序一般使用malloc、realloc、new等函数从堆中分配到块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块;否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。

避免内存泄漏的几种方式:
  • 计数法:使用new或者malloc时,让该数+1,delete或free时,该数-1,程序执行完打印这个数,如果不为0则存在内存泄漏
  • 一定要将基类的析构函数设置为 虚函数
  • 对象数组的释放一定得使用 delete []
  • 有new就有delete,有malloc就有new,保证它们一定成对出现

检测工具:
  • Linux下可以使用Valgrind工具
  • Windows下可以使用CRT库

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值