C++出现exception异常的位置如何定位?

C++抛异常时如何获取异常时的堆栈调用信息 问题背景一般来说,我们使用第三方代码的时候,不可避免的会遇到异常信息。例如调用错误,库中会抛出异常。经常是由于上下文日志不足,我们只能看到catch处的日志,而不清楚异常是哪些函数调用导致。这导致定位问题比较麻烦,经常要花比较长时间去跟进。去网上找了些资料,解决方案方案一:感觉最简单的,还是借助GDB工具,用catch throw命令来帮忙找问题所在。具体的实施方案可以参考这个链接:https:/... 阅读详情

 

有人问过我,在windows系统,如果C++的new产生异常exception,怎么才能知道出错的位置。

 

最简单的 方法是用 _set_new_handler。

 

如果不是 new 产生的, 或者程序非法访问内存了。

 

经过试验,可以先用__try __except捕获它,

在处理函数里面输出callstack调用堆栈,以及exe、dll的名字、地址、范围等信息。

处理完了返回EXCEPTION_CONTINUE_SEARCH,交给C++的try catch来继续处理。

 

 

 

 

#include <windows.h>

#include <stdio.h>

 

 

class win32_tool_help  

{

public:

win32_tool_help();

virtual ~win32_tool_help();

 

static int show_module_list();

};

 

 

#include <tlhelp32.h>

#include <tchar.h>

 

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

win32_tool_help::win32_tool_help()

{

 

}

 

win32_tool_help::~win32_tool_help()

{

 

}

 

int win32_tool_help::show_module_list()

{

HANDLE hSnap = CreateToolhelp32Snapshot( 

TH32CS_SNAPMODULE,

GetCurrentProcessId( )

);

 

MODULEENTRY32 me;

 

me.dwSize = sizeof(me);

 

BOOL ret = Module32First( hSnap, &me );

 

while (TRUE == ret)

{

_tprintf( 

TEXT("hModule = %p, modBaseAddr = %p, modBaseSize = %08X, ")

TEXT("szExePath = %s, szModule = %s /n"), 

me.hModule, me.modBaseAddr, me.modBaseSize,

me.szExePath, me.szModule

);

 

ret = Module32Next( hSnap, &me );

}

 

CloseHandle( hSnap );

 

return 0;

}

 

 

 

class win32_stack_walk  

{

public:

win32_stack_walk();

virtual ~win32_stack_walk();

 

static int start( LPEXCEPTION_POINTERS ep );

 

};

 

 

 

#include <imagehlp.h>

 

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

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

win32_stack_walk::win32_stack_walk()

{

 

}

 

win32_stack_walk::~win32_stack_walk()

{

 

}

 

int win32_stack_walk::start( LPEXCEPTION_POINTERS ep )

{

const DWORD machine_type = IMAGE_FILE_MACHINE_I386;

HANDLE hProcess, hThread;

 

hProcess = GetCurrentProcess();

hThread = GetCurrentThread();

 

STACKFRAME frame = {0};

 

LPVOID ContextRecord = NULL;

 

PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine = NULL; // &ReadProcessMemory;

PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine = &SymFunctionTableAccess;

PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine = &SymGetModuleBase;

PTRANSLATE_ADDRESS_ROUTINE TranslateAddress = NULL;

 

BOOL ret = FALSE;

 

struct handle_frame_addr {

 

static

void set( ADDRESS& addr_s, DWORD addr )

{

addr_s.Mode = AddrModeFlat; 

addr_s.Segment = 0;

addr_s.Offset = addr;

}

 

static 

DWORD get( const ADDRESS& addr_s )

{

return addr_s.Offset;

}

};

 

handle_frame_addr::set( frame.AddrStack , ep->ContextRecord->Esp );

handle_frame_addr::set( frame.AddrFrame , ep->ContextRecord->Ebp );

handle_frame_addr::set( frame.AddrPC    , ep->ContextRecord->Eip );

handle_frame_addr::set( frame.AddrReturn, 0 );

 

do

{

 

printf( "Stack = %08X Frame = %08X PC = %08X Return = %08X /n",  

handle_frame_addr::get( frame.AddrStack ),

handle_frame_addr::get( frame.AddrFrame ),

handle_frame_addr::get( frame.AddrPC ),

handle_frame_addr::get( frame.AddrReturn )

);

ret = StackWalk( machine_type, hProcess, hThread, 

&frame,

ContextRecord, 

ReadMemoryRoutine, 

FunctionTableAccessRoutine, 

GetModuleBaseRoutine, 

TranslateAddress );

 

} while( ret == TRUE );

 

return 0;

}

 

 

#define SHOW_ESP()  /

do { /

DWORD reg_esp = 0; /

__asm { /

mov reg_esp, esp /

} /

printf("esp = %08X/n", reg_esp); /

printf("ep->Esp = %08X/n", ep->ContextRecord->Esp); /

}while(0);

 

 

 

void show_diag_info( LPEXCEPTION_POINTERS ep )

{

win32_stack_walk::start( ep );

win32_tool_help::show_module_list();

}

 

 

void raise01( )

{

printf("%s/n", "raise");

 

CONTEXT ctx_s = {0};

EXCEPTION_POINTERS ep_s;

LPEXCEPTION_POINTERS ep = &ep_s;

ep_s.ContextRecord = &ctx_s;

 

SHOW_ESP();

memset( 0, 1, 1 );

 

}

 

void raise02( )

{

printf("%s/n", "raise");

 

CONTEXT ctx_s = {0};

EXCEPTION_POINTERS ep_s;

LPEXCEPTION_POINTERS ep = &ep_s;

ep_s.ContextRecord = &ctx_s;

 

SHOW_ESP();

 

throw -1;

 

}

int seh_filter01( DWORD ec, LPEXCEPTION_POINTERS ep )

{

printf("%s/n", "seh_filter");

 

SHOW_ESP();

 

show_diag_info( ep );

 

return EXCEPTION_EXECUTE_HANDLER;

}

 

int seh_filter02( DWORD ec, LPEXCEPTION_POINTERS ep )

{

printf("%s/n", "seh_filter");

 

SHOW_ESP();

 

show_diag_info( ep );

 

return EXCEPTION_CONTINUE_SEARCH;

}

 

void test01()

{

DWORD ec = 0;

LPEXCEPTION_POINTERS ep = NULL;

__try

{

raise01();

}

__except( ec = GetExceptionCode(), ep = GetExceptionInformation(), seh_filter01( ec, ep ) )

{

printf("%s/n", "test01->__except");

SHOW_ESP();

}

}

 

void test02_inner()

{

DWORD ec = 0;

LPEXCEPTION_POINTERS ep = NULL;

 

__try

{

raise02();

}

__except( ec = GetExceptionCode(), ep = GetExceptionInformation(), seh_filter02( ec, ep ) )

{

printf("%s/n", "test01->__except");

SHOW_ESP();

}

}

 

void test02()

{

try

{

test02_inner();

}

catch(...)

{

printf("%s/n", "C++ catch(...)");

}

}

 

 

int main(int argc, char* argv[])

{

test01();

test02();

 

return 0;

}

 

Win32程序异常捕获处理 Win32程序异常捕获处理 作者: 朱高磊 日期; 2019-10-24 博客地址:金色世界 背景说明 程序发生异常时,直接以崩溃(闪退)的方式退出,给用户造成不友好的体验。 编程环境C/C++。VS/MFC界面框架 常见崩溃闪退种类及来源 访问错误 数组索引访问越界 指针对象访问越界 访问空指针对象 访问无效指针对象 迭代器访问越界 类型错误 使用C格式进行强制转换。 堆栈溢出... 阅读详情

相关推荐

QT dump文件分析——定位不到源码位置

CONTEXTCONTEXT结构在Windows调试中用于,包含处理器架构相关的寄存器集合。2。

youarenotme的博客 569

确切定位c++代码中异常抛出位置的两个方法 (以VS2010调试为例)

有时候程序crash了,但是不能定位具体的exception在哪里throw的(因为可能函数调用很深,并且有很多try--catch),举个简单的例子: class Test { public: Test(int i) : m_i(i) {} void f() { cout << m_i << endl; throw new Test(6); } ...

weixin_30321709的博客 714

高通Sensor Tuning实战:手把手教你用Chromatix生成并打包bin文件(附避坑指南)

本文详细介绍了高通Sensor Tuning的全流程实战,从Chromatix配置到Bin文件加载验证。通过手把手教程,帮助开发者掌握Chromatix工具链的使用,避免常见配置错误,提升调试效率。特别针对kalama等新一代平台,提供经过验证的解决方案和避坑指南。

ios99的博客 483

CC++定位崩溃代码行的方法

如何根据异常提示信息找出程序出错代码 LINUX 编程 2010-06-23 22:44:10 阅读136 评论0 字号:大中小订阅 看到网上说在debug下可以找到预料的崩溃地址行,但是实际上没有什么用呀。(既然在debug下,那直接用调试器找不更好吗? 费这么大劲干什么)(转的文章在后面)Release版本(指编译器优化后的),要找崩溃地址行就比较费劲了。linux下...

aolan7349的博客 883

评分卡建模学习(一)————数据预处理part.3

目录六、数据处理的思路及代码(一)对缺失值的处理:在我这个数据预处理的part.1板块(二)对异常值的处理:在我这个数据预处理的part.2板块(三)数据归一化、标准化:在我这个数据预处理的part.2板块(四)非结构化数据转变+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++———————————————————————————————————————————++++++++++++++++++++++++++

Morven_dai的博客 898

保姆级教程:用GMT6.1绘制专业地形起伏图(从数据下载到出图避坑)

本文提供了一份详细的GMT6.1绘制地形起伏图的保姆级教程,从环境搭建到数据下载,再到核心绘图命令解析,帮助用户避开常见错误。特别适合科研人员和地理信息爱好者快速掌握专业地形图的绘制技巧,提升工作效率。

weixin_42549723的博客 276

关于C/C++ 异常定位的一些小小心得

hello 大家好,我又回来了,今天想跟大家分享一点有关程序崩溃的一些经验。我们知道C++捕获的异常往往是自己已经定义好的,但是真正的错误层出不穷,往往还没等你捕捉到,程序就已经崩溃了,所以保留有关程序异常的信息就尤为重要。可问题是我怎么知道程序什么时候会崩溃,然后把信息保留呢?这就需要一个工具,就是信号(signal) 我把一些常用的信号及其类型摆在了下面 #define _NSIG ...

github_38263933的博客 605

基于决策树的英雄联盟比赛胜负预测(含完整代码)

在代码中设置随机种子(例如 RANDOM_SEED = 2024)的主要目的是为了确保每次运行代码时,随机过程的结果是一致的。通过绘制不同参数组合下的准确率图,直观地展示了参数对模型性能的影响,帮助读者更好地理解和选择合适的参数。通过设置相同的随机种子(伪随机数),可以确保每次运行代码时,随机数生成器生成的随机数序列是相同的。如果在开发过程中遇到问题,设置固定的随机种子可以帮助你更容易地定位问题,因为每次运行代码时的数据和结果都是一样的。在科学研究和实验中,结果的可重复性是非常重要的。

oisflo的博客 1919

C++ std::exception 异常处理

我们知道,C++的std::exception异常处理,能够通过catch捕获在try代码块中throw的异常。但是,如果function没有通过catch捕获异常,执行该程序生成的可执行文件,会出现异常崩溃。DEBUG下会提示abort() hase been called.Release 下会直接闪退。

669

驻极体咪头信号采集避坑指南:如何用5V单电源搞定0.1mV~1V的音频放大?

本文针对驻极体咪头(ECM)在5V单电源系统中信号采集的常见难题,提供了详细的电路设计指南。文章深入分析了咪头的高输出阻抗与微弱信号特性,重点阐述了采用两级运放(如AD8542)实现低噪声放大、直流偏置叠加以及抗混叠滤波的完整方案,并分享了PCB布局、电源去耦等关键调试技巧,帮助工程师稳定采集0.1mV至1V的音频信号。

weixin_29291069的博客 435

Webpack打包到宝塔上线:前端小白也能搞定的部署保姆教程

本文为前端开发者提供了一份详尽的Webpack项目部署指南。通过宝塔面板的可视化操作,手把手教你如何将Vue3等项目从本地构建、打包,到上传服务器、配置Nginx,最终完成上线部署的全过程,有效解决了新手在项目上线环节的常见难题。

jjj34的博客 223

C++如何快速调试异常位置?

1.明确调试的问题在一个大项目中,很多地方会throw异常,当碰到crash或者抛出异常时,我们需要解决两个问题:第一:异常的源头:究竟哪里抛出了异常第二:异常的处理:捕获异常位置对于异常来说,可能是有我们自己编写的throw触发,也可能是底层库的throw,所以到底是哪里触发的非常难以确认。所以我们需要解决上述两个问题。好在,gdb给我们提供了两个重要的命令。第一个可以使用:catchthro...

Francis的博客 198

第三天:Python基础语法详解

Python代码规范与注释最佳实践 摘要: 本文深度解析Python缩进规则与代码结构的技术规范,包括缩进的底层原理、语法规则和错误处理。详细阐述Python注释系统,涵盖行内注释、文档字符串和类型注释等多种形式,并提供工业级代码组织方案。研究显示,良好的缩进可提升40%的代码识别速度,降低50%的认知负荷。文章还对比了Sphinx、pdoc等主流文档生成工具,给出企业级项目中的注释编写原则和模板建议,帮助开发者构建更可维护的Python代码。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1011

Visual Studio C++ 调试日志与异常定位指南

本指南适用于Visual Studio C++项目,对调试过程中异常抛出、日志输出、行号定位等进行全面解析,帮助开发者快速定位问题。

Darker的博客 2046

基于STM32、HAL库的RN8209D电能计量芯片驱动程序设计

/ 假设电压互感器变比为220V:0.5V,电流互感器变比为20A:5mA。// 电压ADC原始值。// 电流ADC原始值。// 有功功率(W)// 电能(kWh)

corlin6688的博客 469

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【C++11】异常

C语言主要通过错误码的形式处理错误,错误码本质就是对错误信息进行分类编号,拿到错误码以后还要去查询错误信息,比较麻烦。C++11通过异常时抛出⼀个对象,这个对象可以函数更全面的各种信息。异常并不是坏的,反而,它会让我们知道程序中哪里有错误,方便我们快速定位错误,并且不会导致我们的程序直接挂掉。

2401_83251330的博客 921

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

yaml-cpp错误处理终极指南:优雅应对YAML解析异常

**yaml-cpp**作为C++生态中最强大的YAML解析库之一,其卓越的错误恢复机制让开发者能够在面对格式错误或不完整的YAML文件时,依然能够提取有效数据并精准定位问题。这个C++ YAML库通过智能的异常处理策略,确保了即使在部分损坏的配置文件中,应用也能保持稳定运行。 在现实开发中,我们经常遇到配置文件损坏、网络传输错误或人为编辑失误导致的YAML格式问题。传统的解析器通常会直接崩溃或

gitblog_00860的博客 300

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

opencv常见问题:Microsoft C++ 异常:cv::Exception的解决办法汇总

原创 opencv常见问题:Microsoft C++ 异常:cv::Exception的解决 第一步:检查环境配置 第二步 :有关图片路径问题 用”/”,或者用“\”,动手改了一下,没解决,诶呀,这个之前读的也没问题,这个是会引起类似的问题,但是我把图片放在工程里,用的不是绝对路径,所以不影响。 第三步 :图片格式 这个问题是说可能把格式写成了”XXX.png.png”就是本身已经有扩展名了,但...

mk12306的博客 1万+

从C向C++11——异常处理

C++异常处理

墨城烟柳ベ旧人殇的博客 1235

C++异常

程序的错误大致可以分为三种,分别是语法错误、逻辑错误和运行时错误: 语法错误在编译和链接阶段就能发现,只有 100% 符合语法规则的代码才能生成可执行程序。语法错误是最容易发现、最容易定位、最容易排除的错误,程序员最不需要担心的就是这种错误。 逻辑错误是说我们编写的代码思路有问题,不能够达到最终的目标,这种错误可以通过调试来解决。 运行时错误是指程序在运行期间发生的错误,例如除数为 0、内存...

小白的逆袭 482

【C/C++】软件异常状态快速定位技巧

前言 在软件运行过程中遇到的崩溃问题,可能无法找到复现步骤,难以复现。此时使用日志或者Debug方法就很难定位出现异常的代码位置。本文主要讲述如何通过崩溃生成的信息去定位异常代码位置。 Window PC软件崩溃位置定位 以Visual Studio 2017为例,在工程配置属性【生成映射文件】上设置【是】 工程编译完,会在生成目录生成对应的map文件,map文件需要与软件共同打包发布。 当软件运行过程中出现崩溃 ...

wjb123sw99的博客 2847

yaml-cpp容错解析架构深度解析:从异常处理到部分解析的C++实现

在复杂的软件系统中,配置文件解析的健壮性直接影响应用的稳定性。yaml-cpp作为C++生态中功能最完备的YAML解析库,其错误恢复机制设计巧妙,能够在遇到格式问题时依然保持最大程度的可用性。本文将深入剖析yaml-cpp的容错架构,揭示其如何在异常情况下实现部分解析与智能错误报告。 ## 异常处理体系架构设计 yaml-cpp构建了层次分明的异常处理体系,将错误分为三个主要类别: | 异常

gitblog_01084的博客 477

Tabby 终端:把本地 Shell、SSH 和串口调试收进同一窗口的上手指南

Tabby 是一款跨平台终端模拟器,前身叫 Terminus,它把本地 Shell、SSH 连接和串口会话放进同一个窗口管理。如果你经常在本地写代码、远程盯服务器日志、偶尔还要用串口调试硬件,它适合你——不用再在 iTerm2、PuTTY 和别的串口工具之间来回切窗口。 [![Tabby 终端整体界面总览](https://raw.gitcode.com/GitHub_Trending/ta/t

gitblog_00178的博客 914

opencv常见问题(1)Microsoft C++ 异常:cv::Exception

今天,在写程序的时候,突然报了个错误: 错误截图 想必大家遇到错误第一反应都是问度娘! 于是乎,我顺手百度了一下,果然,遇到与此类似的问题还真不少。 0x76BBA932 处(位于 OpenCV.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception,位于内存位置 0x00AEEF48 处。 但是,和我一样的问题却出现在不同的程序中,这就奇

楠国的鱼 4万+

Vorssaint 免费 Mac 菜单栏工具:10 个常用功能装进一个图标,10 分钟装完

我数过自己 Mac 菜单栏上的图标:音量控制一个、剪贴板一个、窗口切换又一个。每装一个 App,就多一块内存、少一截菜单栏。Vorssaint 是个反着来的 Mac 菜单栏工具:单应用音量、窗口切换器、剪贴板历史、系统监控、保持唤醒,全塞进一个图标,数据留在本地,GPL 3.0 开源免费,支持 Apple Silicon + macOS 14 及以上,装完不用注册任何东西。 ## 一、装起来有多

gitblog_00003的博客 494

c++利用SEH异常处理检测内存越界

SEH更适合处理底层硬件异常和系统级错误,适用于 Windows 平台。C++标准异常处理更适合处理程序逻辑错误和高级异常,具有良好的跨平台性和可移植性。C++标准异常处理机制本身是线程安全的,并且支持多线程环境中的异常处理。然而,使用C++标准异常处理时需要注意一些与多线程相关的细节和限制。C++标准异常处理机制支持多线程环境中的异常处理,但需要开发者在多线程程序中谨慎使用。通过在每个线程中正确捕获和处理异常,可以确保多线程程序的稳定性和可靠性。

qq_62784677的博客 930
上一篇: untitled
下一篇: dump file
thtfpcuser
博客等级 码龄20年 13粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值