2310D,Dll,栈跟踪
原文
帮助
有没有想过,如果运行时拥有调试器功能,会怎样?
对系统语言来说,常见问题是解引用空针.这几乎总是会导致崩溃,很难找到该问题,特别是你不是该项目的原始开发者时.
但是,不要害怕,在此我要讲如何在不需要实际附加调试器时获得有用的调试信息.
在Java中,已存在一个叫NullPointerException的方法,它非常有用,因为它准确地显示了崩溃的内容,地点和时间,这就是本文要实现的目标.
检测崩溃(微软C++运行时异常)
每当你的程序崩溃时,程序基本上都会退出,并返回一个负的错误码,或终止信号.
问题是,得不到有意义的错误消息,所以,唯一方法是附加一个调试器,但不是每次都可能,特别是随机发生该错误.
因此,先要检测崩溃,为此,使用Win32API来查找它:
LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER
);
SetUnhandledExceptionFilter函数,参考地址
因此,此函数作用是,在类型运行异常时设置回调,即获得一些有关该异常的信息,如,上面显示的代码0xC..05.
第一个区别是,现在可决定是要继续运行还是处理此错误.
现在,进入回调部分:
extern (窗口) LONG TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{debug{//在D中,可调用`throw`来结束,因为它会自动为我们取栈跟踪throw new Exception("Caught Exception (0x"~toHex(pExceptionInfo.ExceptionRecord.ExceptionCode)~")");//但请继续阅读以了解如何`手动`取栈跟踪}//在此,可控制是否`继续执行`return EXCEPTION_CONTINUE_SEARCH;
}
访问可取错误码.用.而不是->.
取栈跟踪信息
在直接跳转到代码之前,还要包含2个系统库,这九分根据你的语言或构建系统,在D中,可直接从代码中包含库:
debug version(窗口)
{pragma(lib, "psapi.lib");pragma(lib, "dbghelp.lib");
}//Windows
也可在你的构建系统中用-Lpsapi-Ldbghelp来包含,直接放在代码中更清楚.应该放在默认库路径上.
现在,增加可用性的部分:
extern (C) export void backtraced_Register()
{debug{//初化`.pdb`读取进程SymInitialize(GetCurrentProcess(), null, true);//需要取有关文件的行信息SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_DEBUG);SetUnhandledExceptionFilter(&TopLevelExceptionHandler);}
}
现在,细节,分配一些内存来存储异常栈:
debug void printStackTrace()
{enum MAX_DEPTH = 256;void*[MAX_DEPTH] stack;HANDLE process = GetCurrentProcess();ushort frames = RtlCaptureStackBackTrace(0, MAX_DEPTH, stack.ptr, null);SYMBOL_INFO* symbol = cast(SYMBOL_INFO*) calloc((SYMBOL_INFO.sizeof) + 256 * char.sizeof, 1);symbol.MaxNameLen = 255;symbol.SizeOfStruct = SYMBOL_INFO.sizeof;IMAGEHLP_LINEA64 line = void;line.SizeOfStruct = SYMBOL_INFO.sizeof;DWORD dwDisplacement;for (uint i = 0; i < frames; i++){//从当前循环帧中取符号SymFromAddr(process, cast(DWORD64)(stack[i]), null, symbol);//取高级文件信息SymGetLineFromAddr64(process, cast(DWORD64)(stack[i]), &dwDisplacement, &line);//如果用`C++`或D编程,你可能需要一个`"demangle"`函数.来更易阅读符号.此外,`[0..symbol.NameLen]`基本上是来创建一个区间.char[] funcName = demangle(symbol.Name.ptr[0..symbol.NameLen]);auto fname = line.FileName;auto lnum = line.LineNumber;fprintf(stderr, "%s:%i - %.*s\n", fname, lnum, cast(int)funcName.length, funcName.ptr);}free(symbol);
}
现在,有了它,可打印在UnhandledExceptionFilter中的栈跟踪,如下:
结果:
Caught exception (0xC0000005)
-------------------------------------------------------------------+
G:\HipremeEngine\source\hip\systems\game.d:251 - hip::systems::game::GameSystem::addScene::__lambda2
G:\HipremeEngine\modules\util\source\hip\util\concurrency.d:307 - hip::util::concurrency::HipWorkerPool::addOnAllTasksFinished
G:\HipremeEngine\modules\assets\source\hip\assetmanager.d:955 - hip::assetmanager::HipAssetManager::addOnLoadingFinish
G:\HipremeEngine\source\hip\systems\game.d:257 - hip::systems::game::GameSystem::addScene
G:\HipremeEngine\source\hip\systems\game.d:207 - hip::systems::game::GameSystem::startGame
G:\HipremeEngine\source\app.d:238 - app::gameInitialize
G:\HipremeEngine\source\app.d:214 - app::HipremeMain::__lambda4
G:\HipremeEngine\source\hip\global\gamedef.d:85 - hip::global::gamedef::loadDefaultAssets
G:\HipremeEngine\source\app.d:218 - app::HipremeMain
G:\HipremeEngine\source\app.d:296 - app::D main
G:\HipremeEngine\source\app.d:296 - _d_run_main2
G:\HipremeEngine\source\app.d:296 - _d_wrun_main
G:\HipremeEngine\tools\user\build_selector\D\ldc2-1.33.0-beta1-窗口-x64\import\core\internal\entrypoint.d:32 - app::wmain
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288 - __scrt_common_main_seh
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288 - BaseThreadInitThunk
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288 - RtlUserThreadStart
可见,得到了执行如何达到该异常的整个栈跟踪,这使你的程序现在更加可靠,特别是在新项目或DLL上处理其他人代码时.
附录:从DLL取栈跟踪
如果运行的是DLL,特别是在重新加载热代码的系统上,则无法取栈信息(是的,一旦初化异常处理器,它就可在可执行文件和dll代码之间工作).
要解决,你需要沿着dependency.dll文件加载依赖项.pdb,当然,在调试器中运行时都会发生,但是在调用LoadLibrary的独立可执行文件上时,不是这样.
为此,需要一些额外的代码,我叫它DebugLoadLibrary.
void* DebugLoadLibrary(const char* libName)
{import core.sys.windows.winbase;import core.sys.windows.windef;void* ret = LoadLibrary(libName);debug{import core.sys.windows.psapi;MODULEINFO moduleInfo;GetModuleInformation(GetCurrentProcess(), ret, &moduleInfo, MODULEINFO.sizeof);if(!SymLoadModuleEx(GetCurrentProcess(), null, libName, null, cast(ulong)moduleInfo.lpBaseOfDll, moduleInfo.SizeOfImage, null, 0)){throw new Error(format("Failed to load the DLL named ", libName, " pdb"));}}return ret;
}
这样,如果DLL文件内部崩溃了,你会获得一些有用的信息(其栈跟踪),因此,可轻松调试它.
相关文章:
2310D,Dll,栈跟踪
原文 帮助 有没有想过,如果运行时拥有调试器功能,会怎样? 对系统语言来说,常见问题是解引用空针.这几乎总是会导致崩溃,很难找到该问题,特别是你不是该项目的原始开发者时. 但是,不要害怕,在此我要讲如何在不需要实际附加调试器时获得有用的调试信息. 在Java中,已存在一个叫…...
JVS-BI数字大屏设计器:一站式解决方案
数字大屏介绍 数字大屏是当下数据展示、业务监控、指挥调度常见的业务表达形态,常有可视化的图表、效果装饰、事件操作等技术组成酷炫的效果展示。 配置入口 进入JVS-BI(bi.bctools.cn),进入大屏页面,如下图所示 ①…...
uniapp 中添加 vconsole
uniapp 中添加 vconsole 一、安装 vconsole npm i vconsole二、使用 vconsole 在项目的 main.js 文件中添加如下内容 // #ifdef H5 // 提交前需要注释 本地调试使用 import * as vconsole from "vconsole"; new vconsole() // 使用 vconsole // #endif三、成功...
目标检测 YOLOv5 预训练模型下载方法
目标检测 YOLOv5 预训练模型下载方法 flyfish https://github.com/ultralytics/yolov5 https://github.com/ultralytics/yolov5/releases 可以选择自己需要的版本和不同任务类型的模型 后缀名是pt...
第16章_变量、流程控制与游标
第16章_变量、流程控制与游标 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. 变量 在MySQL数据库的存储过程和函数中,可以使用变量来存储查询或计算的中间结果数据,或…...
谁知道腾讯云轻量服务器“月流量”是什么意思?
腾讯云轻量服务器月流量什么意思?月流量是指轻量服务器限制每月流量的意思,不能肆无忌惮地使用公网,流量超额需要另外支付流量费,上海/广州/北京等地域的轻量服务器月流量不够用超额部分按照0.8元/GB的价格支付流量费。阿腾云aten…...
算法笔记【4】-冒泡排序法改进
一、冒泡排序缺点 冒泡排序是一种简单但效率较低的排序算法。冒泡排序通过比较相邻元素并交换位置来实现排序。具体而言,它从数组的第一个元素开始,依次比较相邻的两个元素,如果顺序错误则交换它们的位置,直到整个数组排好序为止…...
cocos creator 资源管理
cocos creator 在使用过程中,经常需要动态加载远端资源,比日说 用户头像,龙骨动画皮肤资源,这些资源不可能都做成 预制体交给 cocos creator 帮助我们管理; 这个时候就需要我们 动态加载远端资源(但是 动态…...
好用的API调试工具推荐:Apipost
随着数字化转型的加速,API(应用程序接口)已经成为企业间沟通和数据交换的关键。而在API开发和管理过程中,API文档、调试、Mock和测试的协作显得尤为重要。Apipost正是这样一款一体化协作平台,旨在解决这些问题…...
贪心算法学习——最长单调递增子序列
目录 编辑 一,题目 二,题目接口 三,解题思路和代码 一,题目 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组…...
银行家算法(Python实现)
银行家算法,以及安全检测算法: import copy# 银行家算法(资源分配合法性) def BankersAlgorithm(Process_num, Resources_num, Request, Max, Available, Allocation, Need):PID Request[PID] # 获取发起请求的进程ID# Step1.如…...
安装终端 ·Terminator
安装终端 在 ROS 中,需要频繁的使用到终端,且可能需要同时开启多个窗口,推荐一款较为好用的终端:**Terminator。**效果如下: 1.安装 sudo apt install terminator2.添加到收藏夹 显示应用程序 —> 搜索 terminator —> 右击 选择 添…...
【Python文件操作的其他例子】
A.Python文件操作的其他例子 当然,以下是一些Python文件操作的其他例子: 1. 读取文件内容: with open(example.txt, r) as f:content f.read()print(content)这个例子会打开名为’example.txt’的文件,读取其内容,…...
使用Terraform管理已经存在的kubernates和默认的节点池
背景: 通过terraform resource "alicloud_cs_managed_kubernetes" "k8s" {...}创建集群时,会产生一个默认的节点池default-nodepool,但是如何去修改这个默认节点池的信息呢? 解决思路: 因为Ter…...
在HTML当中引入Vue控件,以element-ui为例
前情:需要实现一个同时满足按天、按周、按月选择的时间选择器,但是以HTML为基础写的都不太满足我的要求,要么只能按天选择,要么就是想选择久远的时间得点很久,除非自己写捷径,所以就看上了element-ui的这个…...
UE5实现相机水平矫正
UE5实现相机水平矫正 思路,用HIT获得基于相机视角的 离散采样点,然后根据距离相机距离进行权重分析。 距离越近,采样约中心,即越接近人眼注意点,最后算出加权平均高度,赋予给相机,相机将水平旋…...
Word插入Latex语句并编译为数学公式
WPS不可行,正版word可以(垃圾WPS) 选中Latex语句并按下Alt (此处以后补一张图) 该方法不需要额外安装什么插件哦!...
Google Play PolicyBytes 政策更新中文视频 | 2023 年 10 月
Google Play 持续帮助开发者开启成功出海之旅,为用户提供安全优质的应用。也感谢大家与我们携手合作,继续努力将 Google Play 打造为一个安全可信赖的平台。欢迎您观看 Google Play PolicyBytes 中文视频了解 2023 年 10 月政策更新内容,更及…...
pytorch-fastrcnn识别王者荣耀敌方英雄血条
文章目录 前言效果如下实现训练数据获得训练数据和测试数据yaml文件训练py画框文件的修改py测试py升级 前言 最近看王者荣耀视频看到了一个别人提供的一个百里自动设计解决方案,使用一个外设放在百里的二技能上,然后拖动外设在屏幕上滑动,当外设检测到有敌方英雄时外设自动松开…...
阿里云推出通义千问App,提供全方位的协助
🦉 AI新闻 🚀 阿里云推出通义千问App,提供全方位的协助 摘要:阿里云旗下大模型通义千问App登陆各大安卓应用市场,具有超大规模预训练模型,可在创意文案、办公助理、学习助手、趣味生活等方面协助用户。功…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
