软件调试之堆和堆检查

2023-11-13

当用户启动一个程序时,系统会将程序文件从外部存储器(硬盘等)加载到内存中。当程序工作时,需要使用内存空间来放置代码和数据。在使用一段内存之前,程序需要以某种方式(API或库函数)发出申请,接受到申请的一方(内存管理器或C运行库)根据申请者的要求从可用(空闲)空间中寻找满足要求的内存区域分配给申请者。当程序不再需要该空间时应该通过与申请方式相对应的方法归还该空间,即释放。

在大型软件项目中,合理分配和释放内存是非常重要的,由于内存使用不当而导致的各种问题经常成为软件项目的严重阻碍。提高内存的使用率,降低内存分配和释放过程的复杂性一直是软件产业中的永恒话题。JAVA和.net语言的一个共同优势就是可以自动回收不再需要的内存,使程序员可以不用编写释放内存的代码。通过栈来分配局部变量也可以看做是简化内存使用的一种方法

堆是组织内存的另外一种重要方法,是程序在运行期动态申请内存空间的主要途径。与栈空间是由编译器产生的代码自动分配和释放不同,堆上的空间需要程序员自己编写代码来申请(HeapAlloc)和释放(HeapFree),而且分配和释放操作应该严格匹配,忘记释放或多次释放都是不正确的

与栈上的缓冲区溢出类似,如果向堆上的缓冲区写入超过其大小的内容,也会因为溢出而破坏堆上其他内容,可能导致严重的问题,包括程序崩溃。

为了帮助发现堆使用方面的问题,堆管理器,编译器和软件类库提供了很多检查和辅助调试机制。比如,Win32支持参数检查,溢出检查及释放检查等功能。VC编译器设计了专门的调试堆并提供了一系列用来追踪和检查堆使用情况的函数,在编译调试版本的可执行文件时,可以使用这些调试支持来解决内存泄漏等问题。


1.理解堆

栈是分配局部变量和存储函数调用参数以及返回位置的主要场所,系统在创建每个线程时会自动为其创建栈。对于C/C++这样的编程语言,编译器在编译阶段会生成合适的代码来从栈上分配和释放空间,不需要程序员编写任何额外的代码,出于这个原因栈得到了“自动内存”的一个美名。

不过从栈上分配内存也有不足之处,首先,栈空间(尤其是内核态栈)的容量是相对较小的,为了防止栈溢出,不适合在栈上分配特别大的内存区其次,由于栈帧通常是随着函数的调用和返回而创建和消除的,因此分配在栈上的变量只是在函数内有效,这使栈只能分配局部变量,不适合分配需要较长生存期的全局变量和对象。第三,尽管也可以使用_alloca()这样的函数来从栈上分配可变长度的缓冲区,但是这样做回给异常处理(EH)带来麻烦,因此栈也不合适分配运行期才能决定大小(动态大小)的缓冲区

从操作系统的角度看,堆是系统的内存管理功能向应用软件提供服务的一种方式。通过堆,内存管理器(Memory Mamager)将一块较大的内存空间委托给堆管理器(Heap Manager)来管理。堆管理器将大块的内存分割成不同大小的很多个小块来满足应用程序的需要。应用程序的内存需求同城是频繁而且零散的,如果把这些请求都直接传递给位于内核中的内存管理器,那必将影响系统的性能。有了堆管理器,内存管理器就只需要处理大规模的分配请求。这样做不经可以减轻内存管理器的负担,也可以大大缩短应用程序申请内存分配所需的时间,提高程序的运行速度。

用户态的代码应该调用虚拟内存分配API来从内存管理器分配内存。虚拟内存API包括VirtualAlloc,VirtualAllocEx,VirtualFree,VirtualFreeEx,VirtualLock,VirtualUnlock,VIrtualProtect,VIrtualQuery。

内核态的代码可以调用以上API所对应的内核函数,如NtAllocateVirtualMemory, NtProtectVirtualMemory。

为了满足内核空间中的驱动程序等内核态代码的内存分配需要,Windows的内核模块中实现了一系列函数来提供内存零售服务,为了与用户空间的堆管理器相区别,这些函数统称为池管理器(Pool Manager)。池管理器公开了一组驱动程序接口(DDI)以向外提供服务,包括ExAllocatePool,ExAllocatePoolWithTag等

http://www.cnblogs.com/CBDoctor/archive/2013/02/20/2918456.html

(备注:虚拟内存API是通过内存管理器从虚拟内存中分配大块的内存)

与内核模块中的池管理器类似,在NTDLL.DLL中实现了一个通用的堆管理器,目的为用户态的应用程序提供内存服务,通常被称为Win32堆管理器。SDK中公开了一组API来访问Win32堆管理器的功能,如HeapAlloc,HeapFree等

为了支持C的内存分配函数和C++的内存分配运算符(new和delete)(统称为CRT内存分配函数),编译器的C运行库会创建一个专门的堆供这些函数所使用,通常称为CRT堆。根据分配堆块的方式不同,CRT堆有三种工作模式:SBH(Small Block Heap),旧SBH(Old SBH)和系统模式(System Hea

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

软件调试之堆和堆检查 的相关文章

  • cmake

    ubuntu系统当库安装后 需要包含头文件一般在 usr local include 比如 include directories usr local include ImageMagick 7 这样就能调用各种功能头文件 但还要包含 so
  • 数据结构基本概念及算法分析

    文章目录 1 数据结构基本概念 1 1 基本概念和术语 1 1 1 数据 1 1 2 数据元素 1 1 3 数据项 1 1 4 数据对象 1 1 5 数据结构 1 2 逻辑结构与物理结构 1 2 1 逻辑结构 我们最需要关注的问题 1 2
  • 从在浏览器的输入框输入一个网址,到看到网页的内容,这个过程中发生了什么?

    https www cnblogs com ouyang99 p 10284271 html 从在浏览器的输入框输入一个网址 到看到网页的内容 这个过程中发生了什么 当在浏览器地址栏输入网址 如 www baidu com后浏览器是怎么把最
  • 硬件设计27之RS232

    串口通讯 串口通讯 Serial Communication 是一种设备间非常常用的串行通讯方式 因为它简单便捷 大部分电子设备都支持该通讯方式 电子工程师在调试设备时也经常使用该通讯方式输出调试信息 在计算机科学里 大部分复杂的问题都可以
  • js实现简单的视频播放

    功能1 播放暂停切换 思路 准备一个播放的图片和一个暂停的图片 利用标杆思想 设置一个flag变量 播放的时候将flag设置为false 暂停的时候设置为true 如果flag为true则播放同时改变为播放图片 为false则暂停同时改变为
  • 游游的排列构造

    示例1 输入 5 2 输出 3 1 5 2 4 示例2 输入 5 3 输出 2 1 4 3 5 include
  • C语言一行一行读取文件

    C语言中 使用fgets函数可以一行行读du取文件 1 fgets函数 原型 char fgets char buf int bufsize FILE stream 功能 从文件结构体指针stream中读取数据 每次读取一行 说明 读取的数
  • MySQL常用的文本文件导出导入方式总结

    目录 一 导出 1 1 mysql命令导出文本文件 1 2 select into outfile导出文本文件 1 3 mysqldump导出文本文件 二 导入 2 1 mysqlimport导入文本文件 2 2 LOAD DATA INF
  • 笔记记录--基于ccpd数据集利用Paddle OCR训练车牌检测模型

    目录 1 环境搭建 2 数据集划分 3 训练模型 4 推理测试 1 环境搭建 安装Paddle OCR参考 创建环境 conda create n paddle env python 3 8 conda activate paddle en
  • Zookeeper报错Will not attempt to authenticate using SASL解决办法

    Will not attempt to authenticate using SASL unknown error 经过查资料 这个问题与zookeeper里面的zoo cfg配置有关 在程序填写的zookeper的路径 一定与zoo cf
  • CSS网页设计》》

    这是跟着老师做的一个小案例 小小的有了一点成就感 下次努力 div class header div class logo img src img logo png alt logo div div class nav u u div di
  • Linux设备驱动的软件架构思想与设备驱动的基础内容总结

    Linux设备驱动的软件架构思想与设备驱动的基础内容总结 Linux是一个兼容性特别强的一个系统 而兼容性的实现与驱动强大的适应性密不可分 而这个具体的实现是离不开 总线bus和类class的管理方式 Linux使用bus统一的管理一系列相
  • Tomcat 部署方式

    Tomcat中三种部署项目的方法 第一种方法 在tomcat中的conf目录中 在server xml中的
  • 思科三层交换机IPv6静态和默认路由配置

    基础配置 SWA Switch gt ena Switch conf t Switch config host SWA SWA config vlan 10 SWA config vlan vlan 100 SWA config vlan

随机推荐

  • echarts ——timeLine组件

    echarts timeLine组件问题 带timeLine 组件的动态图例 从官网社区中的图例非常完美 拷贝到自己的项目中 下面的1月 2月 只显示0 1 2 3 刚开始以为是获取数据的方法有误 项目空闲期再回看代码发现问题所在 地址 h
  • JavaMail读取收件箱退信邮件/分析邮件附件获取Message_Id

    需求描述 公司最近有个项目邮件通知功能 但是客户上传的邮件地址并不一定存在 以及其他的各种问题 所有希望发送通知后有个回执 及时发现地址存在问题的邮箱 需求分析 经过分析JavaMail可以读取收件箱邮件 我们可以通过对应通知的退信来回写通
  • 爬取12306验证码图片

    author yc import urllib urllib2 import ssl headers User Agent Mozilla 5 0 Windows NT 10 0 WOW64 AppleWebKit 537 36 KHTML
  • c taskspawn 需要申请堆栈的大小 怎么设置_FreeRTOS Task.h/Task.c详解

    刚入门 把自己的理解记录以下 ifndef INC FREERTOS H error include FreeRTOS h must appear in source files before include task h endif 在
  • vaware上安装Linux详细步骤(Slackware10.2)

    环境 HostOS Win2K SP4 GuestOS Slackware10 2 VMware Workstation 5 5 1 b19175 1 建立虚拟机 在VMware上新建一个2 4 x内核的Linux虚拟机 因为Slackwa
  • 消防图像火灾探测器原理

    消防图像火灾探测器是一种基于图像处理技术的先进火灾探测设备 它的工作原理是通过对火灾图像进行分析和识别 实现对火灾的早期探测和报警 这种火灾探测器采用了先进的计算机视觉技术 可以实时监测火灾发生的地点 并在火灾发生之初就能够及时发出警报 从
  • 永擎服务器主板稳定性,永擎双路服务器主板+Platinum铂金8124 8172M 8272CL 8222L套装...

    以下套餐均为单CPU价格 不含主板 不含内存 不要再重复问了 谢谢 套餐一 铂金Platinum 8251 正显版 2 12核24线程 基础频率3 8G 24线程满载4 0G 睿频4 2G 套餐二 铂金 3647 Platinum 8175
  • 如何调试VUE代码(VUE调试利器 vue devtools)

    前言 最新想开发一个前后端分离的项目 一直想开始的 拖延了好久终于决定要对它下手了 最早的时候开发的时候使用的还是JSP 那个时候使用的还是EL表达式 后来切换到Spring和SpringMVC之后采用的是HTML JS的all in on
  • python单元测试框架(继承、unittest参数化、断言、测试报告)

    一 继承 继承能解决什么问题 unittest每个模块都要用到前提条件以及清理 如果有上百个模块 我们要改域名和浏览器 就会工作量很大特别麻烦 这时我们可以用继承的思想只用改一次 我们可以将前提和清理提出来单独放到一个文件里 具体代码如下
  • 图论:Dijkstra算法——最详细的分析,图文并茂,一次看懂!

    文章目录 1 Dijkstra算法简介 2 算法实现范例 3 邻接矩阵 4 Dijkstra 算法的 C 描述 5 Dijkstra 算法的 Matlab 描述 6 温故知新 1 Dijkstra算法简介 背景 迪杰斯特拉算法 Dijkst
  • Java中double类型大小比较的五种方法

    文章目录 1 使用BigDecimal 2 使用包装类Double 3 在误差范围内运行相等 4 转换成字符串 5 使用doubleToLongBits 方法 在Java中 int类型数据的大小比较可以使用双等号 double类型则不能使用
  • 设置SSH密钥对的必要性

    SSH介绍 SSH 为 Secure Shell 的缩写 由 IETF 的网络小组 Network Working Group 所制定 SSH 为建立在应用层基础上的安全协议 SSH 是较可靠 专为远程登录会话和其他网络服务提供安全性的协议
  • golang加载双向认证加密的证书key文件

    证书的key是可以加密保存的 我们需要进行解密加载 func MyLoadX509KeyPair certFile keyFile password string tls Certificate error certPEMByte err
  • 开放API接口或URL链接给第三方使用

    使用场景 场景1 应用做到一定程度后 会有一些第三方用户或机构要对接部分的功能进入他们自己的应用 比如 要通过URL的方式提供一个含有加密视频文件的H5页面给第三方使用 实现思路 1 后台管理系统给不同的第三方开权限 分别提供AppID和A
  • 学习率衰减

    在训练深度神经网络时 通常会随着训练的进行降低学习率 这可以通过使用预定义的学习率计划或自适应学习率方法来完成 学习率表 学习率时间表旨在根据预先定义的时间表降低学习率 从而在训练过程中调整学习率 常见的学习率时间表包括基于时间的衰减 逐步
  • AES算法的CBC和ECB模式!——密钥加密

    一 AES算法 AES Advanced Encryption Standard 是一种对称密钥加密算法 AES算法采用分组密码的方式 将明文划分成固定长度的数据块 对每个数据块进行加密 最终得到密文 AES算法的密钥长度可以为128位 1
  • 利用Netty构建自定义协议的通信

    在复杂的网络世界中 各种应用之间通信需要依赖各种各样的协议 比如 HTTP Telnet FTP SMTP等等 在开发过程中 有时候我们需要构建一些适应自己业务的应用层协议 Netty作为一个非常优秀的网络通信框架 可以帮助我们完成自定义协
  • 【Linux + 安装库】Ubuntu18.4.0下安装gmp+ntl+crytpo++库的相关操作

    一 装Ubuntu 1 虚拟机下装好的ubuntu系统安装编译器 首先需要添加源 代码 sudo add apt repository ppa ubuntu toolchain r test 2 添加源之后 安装编译器 gcc安装 sudo
  • Spring Boot 学习研究笔记(十二)Dcoker 中部署SpringBoot jar包

    Linux Centos8 使用 DOCKER 部署JAR包 1 进入项目根目录 cd project 2 创建存放jar包的目录 mkdir springboot test 3 进入 project springboot test 编写D
  • 软件调试之堆和堆检查

    当用户启动一个程序时 系统会将程序文件从外部存储器 硬盘等 加载到内存中 当程序工作时 需要使用内存空间来放置代码和数据 在使用一段内存之前 程序需要以某种方式 API或库函数 发出申请 接受到申请的一方 内存管理器或C运行库 根据申请者的