#include
#include
#define CRTDBG_MAP_ALLOC
#include
#include using namespace std;//客户端块挂钩回调
void DumpClientFunction(void* userPortion, size_t blockSize)
{cout << userPortion << ":"<< blockSize<
// _crtBreakAlloc = 99;//设置内存分配编号断点//_CLIENT_BLOCK块内存转储挂钩函数_CrtSetDumpClient(DumpClientFunction);//客户端块是针对MFC程序 CObject 此处没作用//设置报告模式_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);//内存块检测点_CrtMemState s1, s2, s3;_CrtMemCheckpoint(&s1); auto p = new double;auto pr = new double;auto pc = DBG_NEW char;//_CLIENT_BLOCK分配动作_CrtMemCheckpoint(&s2);if (_CrtMemDifference(&s3, &s1, &s2))_CrtMemDumpStatistics(&s3);//内存泄漏转储_CrtDumpMemoryLeaks();using Fntype = void(*)();HINSTANCE hdll = LoadLibrary("memd.dll");Fntype fn=(Fntype)GetProcAddress(hdll, "Print");//此处对于链接器所见链接性不会有任何影响,因为链接器不需要管,是在运行期直接寻址fn();return 0;
}
CRT 调试库使用
C 运行时 (CRT) 库提供广泛的调试支持。 若要使用 CRT 调试库之一,必须使用 链接/DEBUG并使用 、 /MTd或/MDd 进行编译。
客户端块挂钩
使用 _CrtSetDumpClient 安装挂钩函数后,每次转储块时 _CLIENT_BLOCK 都会调用它。 然后,可以使用 _CrtReportBlockType 获取有关转储块的类型或子类型的信息。
利用CRT调式堆
调式堆中的块类型
_NORMAL_BLOCK【正常块】
调用 malloc 或 calloc 创建 Normal 块。 如果打算仅使用 Normal 块,并且不需要客户端块,则可能需要定义 _CRTDBG_MAP_ALLOC。 _CRTDBG_MAP_ALLOC 将所有堆分配调用映射到调试版本中的调试等效项。 它允许在相应的块标头中存储有关每个分配调用的文件名和行号信息。
_CRT_BLOCK【运行时库分配的块】
由许多运行库函数内部分配的内存块被标记为 CRT 块,以便可以单独处理这些块。 因此,泄漏检测和其他操作可能不受它们影响。 分配永不可以分配、重新分配或释放任何 CRT 类型的块。
_CLIENT_BLOCK【客户端自定义标记块】
出于调试目的,应用程序可以专门跟踪一组给定的分配,方法是使用对调试堆函数的显式调用将它们作为该类型的内存块进行分配。 例如,MFC 将所有 CObject 对象分配为客户端块;其他应用程序可能会在客户端块中保留不同的内存对象。 还可以指定客户端块的子类型,使跟踪粒度更大。 若要指定客户端块的子类型,请将该数字向左移 16 位,并使用 _CLIENT_BLOCK 对其进行 OR 运算。 例如:
C++
#define MYSUBTYPE 4
freedbg(pbData, _CLIENT_BLOCK|(MYSUBTYPE<<16));
可以使用 安装 _CrtSetDumpClient客户端提供的用于转储客户端块中存储的对象的挂钩函数,然后在调试函数转储客户端块时调用。 此外, _CrtDoForAllClientObjects 可用于调用应用程序为调试堆中的每个客户端块提供的给定函数。
_FREE_BLOCK【仿释放块:释放动作不移除块;而是给其标记为仿释放标记】
通常,所释放的块将从列表中移除。 若要检查释放的内存是否未写入或模拟内存不足的情况,可以将释放的块保留在链接列表中,标记为可用,并使用当前0xDD) (已知字节值填充。
_IGNORE_BLOCK【把一定时间内的分配动作产生的块标记为 可忽略块】
可以在一定时间间隔内关闭调试堆操作。 在该时间段内,内存块保留在列表上,但被标记为“忽略”块。
详见 _CrtSetDbgFlag函数说明
配置调试堆【调式模式会使用到堆函数的调式版本,这些版本函数被调用时会对上下cookie已经debug head进行检查】
对堆函数(例如 malloc、free、calloc、realloc、new 和 delete)的所有调用均解析为这些函数在调试堆中运行的调试版本。 释放内存块时,调试堆自动检查已分配区域两侧的缓冲区的完整性,并在发生覆盖时发出错误报告。
使用调试堆 将应用程序的调试版本与 C 运行时库的调试版本链接。
线程栈模块堆:不同的模块所用的运行时堆不同,CRT调式堆函数只能检查他们所在运行时堆的信息
上一篇:Hive的UDF实现两种简单方法+通过编译源码添加UDF
下一篇:骷髅病毒分析