C++使用new 和new[]操作符分配内存时的调用栈跟踪显示2

2023-05-16

我们可以通过这个技术分析内存泄漏的调用函数和位置。

 

#include <Windows.h>
#include <ImageHlp.h>
#include <iostream>
#include <string>
#include <atlutil.h>
#include <memory>

#pragma comment(lib, "ImageHlp.lib")

LONG DumpExceptStack(LPEXCEPTION_POINTERS pException_);
void TriggerDump();


void* __CRTDECL  operator new(size_t const size)
{
	TriggerDump();

	for (;;)
	{
		if (void* const block = malloc(size))
		{
			return block;
		}

		if (_callnewh(size) == 0)
		{
			if (size == SIZE_MAX)
			{
				throw std::exception("bad alloc, SIZE_MAX");

			}
			else
			{
				throw std::exception("bad alloc");
			}
		}
	}
}

int main()
{
	std::cout << "new operator track back" << std::endl;;
	char* sz = new char;
	delete[] sz;

	sz = new char[24];
	delete[] sz;
}

#ifndef STATUS_POSSIBLE_DEADLOCK
#define STATUS_POSSIBLE_DEADLOCK         ((DWORD)0xC0000194L)
#endif

struct  SExceptDescTabe
{
	DWORD dwCode;
	const char* szDesc;
}g_ExceptDescTable[] =
{
	{ EXCEPTION_ACCESS_VIOLATION,  ("EXCEPTION_ACCESS_VIOLATION")},
	{ EXCEPTION_DATATYPE_MISALIGNMENT, ("EXCEPTION_DATATYPE_MISALIGNMENT")},
	{ EXCEPTION_BREAKPOINT, ("EXCEPTION_BREAKPOINT")},
	{ EXCEPTION_SINGLE_STEP, ("EXCEPTION_SINGLE_STEP")},
	{ EXCEPTION_ARRAY_BOUNDS_EXCEEDED, ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED")},

	{ EXCEPTION_FLT_DENORMAL_OPERAND, ("EXCEPTION_FLT_DENORMAL_OPERAND")},
	{ EXCEPTION_FLT_DIVIDE_BY_ZERO, ("EXCEPTION_FLT_DIVIDE_BY_ZERO")},
	{ EXCEPTION_FLT_INEXACT_RESULT,  ("EXCEPTION_FLT_INEXACT_RESULT")},
	{ EXCEPTION_FLT_INVALID_OPERATION, ("EXCEPTION_FLT_INVALID_OPERATION")},
	{ EXCEPTION_FLT_OVERFLOW, ("EXCEPTION_FLT_OVERFLOW")},

	{ EXCEPTION_FLT_STACK_CHECK, ("EXCEPTION_FLT_STACK_CHECK")},
	{ EXCEPTION_FLT_UNDERFLOW, ("EXCEPTION_FLT_UNDERFLOW")},
	{ EXCEPTION_INT_DIVIDE_BY_ZERO, ("EXCEPTION_INT_DIVIDE_BY_ZERO")},
	{ EXCEPTION_INT_OVERFLOW, ("EXCEPTION_INT_OVERFLOW")},
	{ EXCEPTION_PRIV_INSTRUCTION,  ("EXCEPTION_PRIV_INSTRUCTION")},

	{ EXCEPTION_IN_PAGE_ERROR, ("EXCEPTION_IN_PAGE_ERROR")},
	{ EXCEPTION_ILLEGAL_INSTRUCTION, ("EXCEPTION_ILLEGAL_INSTRUCTION")},
	{ EXCEPTION_NONCONTINUABLE_EXCEPTION, ("EXCEPTION_NONCONTINUABLE_EXCEPz`TION")},
	{ EXCEPTION_STACK_OVERFLOW, ("EXCEPTION_STACK_OVERFLOW")},
	{ EXCEPTION_INVALID_DISPOSITION, ("EXCEPTION_INVALID_DISPOSITION")},

	{ EXCEPTION_GUARD_PAGE, ("EXCEPTION_GUARD_PAGE")},
	{ EXCEPTION_INVALID_HANDLE,  ("EXCEPTION_INVALID_HANDLE")},
	{ EXCEPTION_POSSIBLE_DEADLOCK, ("EXCEPTION_POSSIBLE_DEADLOCK")},
};

struct FunctionCall
{
	char FunctionName[128];
	char FileName[512];
	int	LineNumber;
};

void TriggerDump()
{
	std::cout << "\n\n----------call stack---------\n" << std::endl;
	__try
	{

		RaiseException(0xC0000194L + 12, 0, 0, NULL);
	}
	__except (DumpExceptStack(GetExceptionInformation()), 1)
	{
	}
}

LONG DumpExceptStack(LPEXCEPTION_POINTERS pException_)
{
	char _strStack[8192];
	_strStack[0] = '\0';
	CONTEXT* _pContext;
	CONTEXT _ctxt;
	memset(&_ctxt, 0, sizeof(_ctxt));
	if (!pException_)
	{
		return 0;
#if  0
#if defined(_WIN64)
		__asm mov _ctxt.Rsp, RSP;
		__asm mov _ctxt.Rbp, RBP;
#elif defined(WIN32)
		__asm mov _ctxt.Esp, Esp;
		__asm mov _ctxt.Ebp, Ebp;
#endif
#endif
		_pContext = &_ctxt;
	}
	else
		_pContext = pException_->ContextRecord;

	// Initialize stack frame
	STACKFRAME64 sf;
	memset(&sf, 0, sizeof(STACKFRAME));

#if defined(_WIN64)
	sf.AddrPC.Offset = _pContext->Rip;
	sf.AddrStack.Offset = _pContext->Rsp;
	sf.AddrFrame.Offset = _pContext->Rbp;
#elif defined(WIN32)
	sf.AddrPC.Offset = _pContext->Eip;
	sf.AddrStack.Offset = _pContext->Esp;
	sf.AddrFrame.Offset = _pContext->Ebp;
#endif
	sf.AddrPC.Mode = AddrModeFlat;
	sf.AddrStack.Mode = AddrModeFlat;
	sf.AddrFrame.Mode = AddrModeFlat;

	DWORD _dwMachineType = 0;
	char* chArchVar;
	size_t requiredSize;
	getenv_s(&requiredSize, NULL, 0, "PROCESSOR_ARCHITECTURE");
	chArchVar = (char*)malloc(requiredSize * sizeof(char));
	getenv_s(&requiredSize, chArchVar, requiredSize, "PROCESSOR_ARCHITECTURE");
	if (chArchVar)
	{
		if ((!strcmp("EM64T", chArchVar)) || !strcmp("AMD64", chArchVar))
			_dwMachineType = IMAGE_FILE_MACHINE_AMD64;
		else if (!strcmp("x86", chArchVar))
			_dwMachineType = IMAGE_FILE_MACHINE_I386;
	}

	free(chArchVar);
	if (0 == _dwMachineType)
		return EXCEPTION_EXECUTE_HANDLER;

	DWORD _dwCode = pException_ ? pException_->ExceptionRecord->ExceptionCode : 0;
	int _nTableCount = sizeof(g_ExceptDescTable) / sizeof(g_ExceptDescTable[0]);
	bool _bFind = false;
	for (int _i = 0; _i < _nTableCount; ++_i)
	{
		if (_dwCode == g_ExceptDescTable[_i].dwCode)
		{
			strcat(_strStack, g_ExceptDescTable[_i].szDesc);
			strcat(_strStack, "\r\n");
			_bFind = true;
			break;
		}
	}

	char _sz[256];
	if (!_bFind)
	{
		sprintf_s(_sz, "except code: 0x%x\r\n", _dwCode);
		strcat(_strStack, _sz);
	}


	// Walk through the stack frames.
	HANDLE hProcess = GetCurrentProcess();
	HANDLE hThread = GetCurrentThread();
	if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
	{
		SymCleanup(hProcess);
		return EXCEPTION_EXECUTE_HANDLER;
	}

	while (StackWalk64(_dwMachineType, hProcess, hThread, &sf, _pContext, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0))
	{
		if (sf.AddrFrame.Offset == 0)
			break;

		// 1. Get function name at the address
		const int nBuffSize = (sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64);
		ULONG64 symbolBuffer[nBuffSize];
		PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;

		pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
		pSymbol->MaxNameLen = MAX_SYM_NAME;

		FunctionCall curCall;
		curCall.FunctionName[0] = '\0';
		curCall.FileName[0] = '\0';
		curCall.LineNumber = 0;

		DWORD64 dwSymDisplacement = 0;
		if (SymFromAddr(hProcess, sf.AddrPC.Offset, &dwSymDisplacement, pSymbol))
		{
			strcpy(curCall.FunctionName,  pSymbol->Name);
		}

		//2. get line and file name at the address
		IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
		DWORD dwLineDisplacement = 0;

		if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
		{
			strcpy(curCall.FileName, (lineInfo.FileName));
			curCall.LineNumber = lineInfo.LineNumber;
		}

		CStackDumper::_ATL_SYMBOL_INFO info;
		sprintf_s(_sz, "%llX: ", sf.AddrPC.Offset);
		strcat(_strStack, _sz);
		if (CStackDumper::ResolveSymbol(hProcess, UINT_PTR(sf.AddrPC.Offset), info))
		{
			strcat(_strStack, info.szModule);
			strcat(_strStack, " ");
			strcat(_strStack, info.szSymbol);
			strcat(_strStack, "\r\n");
		}
		else
			strcat(_strStack, "symbol not found");

		strcat(_strStack,  "File: ");
		strcat(_strStack,  curCall.FileName);
		strcat(_strStack,  "\r\n");
		strcat(_strStack,  "Func: ");
		strcat(_strStack,  curCall.FunctionName);
		strcat(_strStack,  "\r\n");
		sprintf_s(_sz, "Line: %d", curCall.LineNumber);
		strcat(_strStack,  _sz);
		strcat(_strStack,  "\r\n\r\n");
	}

	SymCleanup(hProcess);
	std::cout << _strStack << std::endl;

	return EXCEPTION_EXECUTE_HANDLER;
}

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

C++使用new 和new[]操作符分配内存时的调用栈跟踪显示2 的相关文章

  • new与delete正确用法

    说明 xff1a 推荐使用如下宏 xff0c 可以在一定程度上避免使用空指针 xff0c 野指针的问题 define HW NEW var classname do try var 61 new classname catch var 61
  • 重载全局new和delete

    程序代码 如下所示 xff1a span class token macro property span class token directive keyword include span span class token string
  • The new driver class is `com.mysql.cj.jdbc.Driver‘.

    记一次数据库连接数据库报错 报错提示 xff1a Loading class com mysql jdbc Driver 39 This is deprecated The new driver class iscom mysql cj j
  • 重载new和delete检测内存泄漏

    内存泄漏就是new出来的内存没有通过delete合理的释放 重载new和delete检测内存泄漏原理是 xff1a 在重载的new中记录内存分配情况 xff0c 在重载的delete中删除内存分配记录 xff0c 从而跟踪所有内存分配信息
  • c++ 中的重载全局new,delete

    最近做一个小项目 xff0c 对c 43 43 又有很多新的理解 实在不的不让人发出感叹 xff0c c 43 43 太强大了 xff0c 绝对不是一朝一夕就可以领悟她的内涵的 首先我们要清楚 xff0c 为什么我们要重载new xff0c
  • android new intent,Android:关于onNewIntent()触发机制及注意事项

    在阅读该篇日志前 xff0c 先熟悉一下Android的四种启动模式 xff0c 因为onNewIntent并不是在所有启动模式下都会执行的 一 onNewIntent 在IntentActivity中重写下列方法 xff1a onCrea
  • new和malloc的区别

    new和malloc的区别 1 new从自由存储区上分配内存 xff0c malloc从堆上分配内存 自由存储区是C 43 43 基于new操作符的一个抽象概念 xff0c 凡是通过new操作符进行内存申请 xff0c 该内存即为自由存储区
  • TypeError: __new__() got an unexpected keyword argument 'serialized_options'

    Python 2 7 12 default Nov 12 2018 14 36 49 GCC 5 4 0 20160609 on linux2 Type 34 help 34 34 copyright 34 34 credits 34 or
  • 用new调用函数的四步走

    JS规定 xff0c 使用new调用函数会进行四步走 xff1a 1 函数体内会自动创建出一个空白对象 2 函数的上下文 xff08 this xff09 会自动指向这个对象 3 函数体内的语句会执行 4 函数会自动返回上下文对象 xff0
  • 让人混淆的Person p=new Person();和Person p=null;

    一 对 Person p 61 new Person 的理解 要理解这个问题 xff0c 首先要知道整个过程中内存中发生了什么 xff01 我们知道 xff0c 内存中我们最常用的就是三个 xff1a 栈 堆 方法区 其中对于基本值类型和引
  • c++---构造函数以及new和delete的使用

    目录 一 构造函数和析构函数的语法 二 构造函数的分类和调用 三 拷贝构造函数的调用时机 1 用已经创建好的对象来初始化新的对象 2 用值传递的方式 给函数参数传值 3 以值的方式 返回局部对象 四 构造函数调用规则 五 初始化列表 六 类
  • C++(1) 指针 new 和delete

    1 概念 new typeName pointer name 61 new typeName delete delete pointer name 注意 xff1a 1 new之后要判断 xff0c 指针是否为NULL xff0c 内存被耗
  • new Map()

    1 new Map let data 61 new Map data set key value 添加一个新建元素到映射 Map 1 key 61 gt value data get key 返回映射中的指定元素 data has key
  • c++中 new的使用方法

    c 43 43 中 xff0c new的用法很灵活 xff0c 这里进行了简单的总结 1 new 分配这种类型的一个大小的内存空间 并以括号中的值来初始化这个变量 2 new 分配这种类型的n个大小的内存空间 并用默认构造函数来初始化这些变
  • 重载new和delete检测内存泄漏

    内存泄漏就是new出来的内存没有通过delete合理的释放 重载new和delete检测内存泄漏原理是 xff1a 在重载的new中记录内存分配情况 xff0c 在重载的delete中删除内存分配记录 xff0c 从而跟踪所有内存分配信息
  • PHP new mysqli()连接

    1 首先在mysql命令控制台新建数据库 mysql gt create database test Query OK 1 row affected 0 04 sec mysql gt use test Database changed m
  • 攻防世界 web 不能按的按钮 disabled_button

    f12打开开发者工具 点击查看器这一栏 定位到它的图标处 双击进入 里面有代码如下 一般有两种方法 方法一 删除代码 disabled 然后点击网页上的flag图标就可以得到flag了 方法二 将disabled 改为disabled fa
  • C++ malloc/free/new/delete详解(内存管理)

    这里写目录标题 malloc free 典型用法 内存分配 实现过程 brk和mmap 申请小于128k的内存 申请大于128k的内存 释放内存 brk和mmap的区别 new delete 典型用法 内存分配 实现过程 new delet
  • Haxe: class, object, new and constructor

    haxe 类 对象 new 和 构造函数 package if neko import neko Lib import neko io File end class Thing public function new trace new f
  • memset in C++ and C

    definition memset是计算机中C C 语言函数 将s所指向的某一块内存中的前n个 字节的内容全部设置为ch指定的ASCII值 第一个值为指定的内存地址 块的大小由第三个参数指定 这个函数通常为新申请的内存做初始化工作 其返回值

随机推荐

  • Latex的学习

    因为种种原因 xff0c 要学一下latex 一个非常快速的 Latex 入门教程 哔哩哔哩 bilibili 适用 xff1a 快速切换格式和排版 即会将文档的内容和排版区分开 markdown适用于轻量文字编辑 常用工具 xff1a 1
  • VTK经典四格图

    右下角的是使用Volume绘制的三维图
  • vim常用指令类表

    最近开始Linux环境下编程 xff0c 有时需要使用vim浏览和修改代码 xff0c 特意学习了一下 xff0c 并整理了一些常用指令 xff0c 如下所示 VIM常用命令 工作模式 正常模式 Esc编辑模式 i可视选择模式 v文件 打开
  • 2021-06-23

    root 64 localhost cat usr share applications Lxg desktop Desktop Entry Name 61 Lxg Type 61 Application Exec 61 home lys
  • gcc编译过程

    1 下载相应代码库 xff0c 解压到一个大的文件夹的各子文件夹 2 执行脚本 cd gmp 5 0 0 make clean configure disable shared enable static prefix 61 usr loc
  • 【vscode】去除黄色波浪下划线

    vscode 去除黄色波浪下划线 vscode在使用过程中 xff0c 如果出现变量名下方出现黄色波浪线 xff0c 影响编程效率 可能原因是由于安装了pylint这个库 xff0c 并没有进行合适的设置 我们可以在设置中查找 34 pyt
  • Volume 多边形裁剪测试

    vtk自带了一个Volume剪切的例子 xff0c 可以用隐函数确定的剪切面裁剪vtkImageData 本人对该例子代码略加修改 xff0c 剪切口为一个封闭的梯形 其代码和配置文件如下 目录 ClipVolume cxx CMakeLi
  • VTK应用程序连接出现vtkRenderingOpenGL_AutoInit_Construct(void)报错解决方法一则

    出现vtkRenderingOpenGL AutoInit Construct void 报错 xff1a xff08 1 xff09 具体报错为 xff1a error LNK2019 无法解析的外部符号 34 void cdecl vt
  • 在Debian下安装输入法的过程

    执行下面的命令 xff1a sudo apt get install software properties common apt add repository ppa fcitx team nightly sudo apt get upd
  • 【MITK】在Windows中编译MITK

    1 在Git Bash执行下面的命令 cd D mkdir MITK cd MITK git clone https phabricator mitk org source mitk git MITK cd MITK cmake S B W
  • 解决WSL中Debian显示中文乱码的问题

    1 sudo apt get install locales 2 sudo dpkg reconfigure locales 勾选 zh CN XX 3 sudo locale gen 4 sudo apt get install ttf
  • WSL中Debian配置中文输入法

    1 sudo apt install dbus x11 im config fonts noto fcitx fcitx pinyin fcitx sunpinyin fcitx googlepinyin 2 fcitx autostart
  • Windows 下获得当前线程上下文并保存到dump文件测试之2

    include lt Windows h gt include lt Dbghelp h gt include lt excpt h gt include lt exception gt include lt iostream gt inc
  • 使用函数钩子实现打印throw异常时的调用栈

    include lt Windows h gt include lt winnt h gt include lt Dbghelp h gt include lt excpt h gt include lt ehdata h gt inclu
  • MFC/QT混合编程时使用QMessageBox一例

    MFC QT混合编程的方法可以参考这个链接 xff1a MFC QT混合编程官方方法 1 使用QMessageBox可以这样 xff1a void CJxDicomerApp OnTest QWinWidget parent 61 new
  • C++流编程学习例子01

    C 43 43 流有一个类继承体制 xff0c 符合C 43 43 类的语义 下面的代码使用std cout作为std ostream引用 xff0c 能够正确输出信息 我们也可以用ofstream ostringstream等做类似操作
  • 洛谷P1593 因子和

    题目描述 输入两个正整数a和b xff0c 求a b的因子和 结果太大 xff0c 只要输出它对9901的余数 输入输出格式 输入格式 xff1a 仅一行 xff0c 为两个正整数a和b 0 a b 50000000 输出格式 xff1a
  • android layout view 编辑器

    DroidDraw is a graphical user interface GUI builder for the Android platform 下载地址 xff1a http code google com p droiddraw
  • new[]和new调用地址的简单跟踪

    重写这两个操作符 xff0c 插入打印语句 xff0c 可获得调用地址 代码如下 xff1a include lt Windows h gt include lt iostream gt include lt stdlib h gt inc
  • C++使用new 和new[]操作符分配内存时的调用栈跟踪显示2

    我们可以通过这个技术分析内存泄漏的调用函数和位置 include lt Windows h gt include lt ImageHlp h gt include lt iostream gt include lt string gt in