当前位置: 首页 > news >正文

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数字大屏设计器:一站式解决方案

数字大屏介绍 数字大屏是当下数据展示、业务监控、指挥调度常见的业务表达形态&#xff0c;常有可视化的图表、效果装饰、事件操作等技术组成酷炫的效果展示。 配置入口 进入JVS-BI&#xff08;bi.bctools.cn&#xff09;&#xff0c;进入大屏页面&#xff0c;如下图所示 ①…...

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章_变量、流程控制与游标 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 1. 变量 在MySQL数据库的存储过程和函数中&#xff0c;可以使用变量来存储查询或计算的中间结果数据&#xff0c;或…...

谁知道腾讯云轻量服务器“月流量”是什么意思?

腾讯云轻量服务器月流量什么意思&#xff1f;月流量是指轻量服务器限制每月流量的意思&#xff0c;不能肆无忌惮地使用公网&#xff0c;流量超额需要另外支付流量费&#xff0c;上海/广州/北京等地域的轻量服务器月流量不够用超额部分按照0.8元/GB的价格支付流量费。阿腾云aten…...

算法笔记【4】-冒泡排序法改进

一、冒泡排序缺点 冒泡排序是一种简单但效率较低的排序算法。冒泡排序通过比较相邻元素并交换位置来实现排序。具体而言&#xff0c;它从数组的第一个元素开始&#xff0c;依次比较相邻的两个元素&#xff0c;如果顺序错误则交换它们的位置&#xff0c;直到整个数组排好序为止…...

cocos creator 资源管理

cocos creator 在使用过程中&#xff0c;经常需要动态加载远端资源&#xff0c;比日说 用户头像&#xff0c;龙骨动画皮肤资源&#xff0c;这些资源不可能都做成 预制体交给 cocos creator 帮助我们管理&#xff1b; 这个时候就需要我们 动态加载远端资源&#xff08;但是 动态…...

好用的API调试工具推荐:Apipost

随着数字化转型的加速&#xff0c;API&#xff08;应用程序接口&#xff09;已经成为企业间沟通和数据交换的关键。而在API开发和管理过程中&#xff0c;API文档、调试、Mock和测试的协作显得尤为重要。Apipost正是这样一款一体化协作平台&#xff0c;旨在解决这些问题&#xf…...

贪心算法学习——最长单调递增子序列

目录 ​编辑 一&#xff0c;题目 二&#xff0c;题目接口 三&#xff0c;解题思路和代码 一&#xff0c;题目 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组…...

银行家算法(Python实现)

银行家算法&#xff0c;以及安全检测算法&#xff1a; import copy# 银行家算法&#xff08;资源分配合法性&#xff09; def BankersAlgorithm(Process_num, Resources_num, Request, Max, Available, Allocation, Need):PID Request[PID] # 获取发起请求的进程ID# Step1.如…...

安装终端 ·Terminator

安装终端 在 ROS 中&#xff0c;需要频繁的使用到终端&#xff0c;且可能需要同时开启多个窗口&#xff0c;推荐一款较为好用的终端:**Terminator。**效果如下: 1.安装 sudo apt install terminator2.添加到收藏夹 显示应用程序 —> 搜索 terminator —> 右击 选择 添…...

【Python文件操作的其他例子】

A.Python文件操作的其他例子 当然&#xff0c;以下是一些Python文件操作的其他例子&#xff1a; 1. 读取文件内容&#xff1a; with open(example.txt, r) as f:content f.read()print(content)这个例子会打开名为’example.txt’的文件&#xff0c;读取其内容&#xff0c;…...

使用Terraform管理已经存在的kubernates和默认的节点池

背景&#xff1a; 通过terraform resource "alicloud_cs_managed_kubernetes" "k8s" {...}创建集群时&#xff0c;会产生一个默认的节点池default-nodepool&#xff0c;但是如何去修改这个默认节点池的信息呢&#xff1f; 解决思路&#xff1a; 因为Ter…...

在HTML当中引入Vue控件,以element-ui为例

前情&#xff1a;需要实现一个同时满足按天、按周、按月选择的时间选择器&#xff0c;但是以HTML为基础写的都不太满足我的要求&#xff0c;要么只能按天选择&#xff0c;要么就是想选择久远的时间得点很久&#xff0c;除非自己写捷径&#xff0c;所以就看上了element-ui的这个…...

UE5实现相机水平矫正

UE5实现相机水平矫正 思路&#xff0c;用HIT获得基于相机视角的 离散采样点&#xff0c;然后根据距离相机距离进行权重分析。 距离越近&#xff0c;采样约中心&#xff0c;即越接近人眼注意点&#xff0c;最后算出加权平均高度&#xff0c;赋予给相机&#xff0c;相机将水平旋…...

Word插入Latex语句并编译为数学公式

WPS不可行&#xff0c;正版word可以&#xff08;垃圾WPS&#xff09; 选中Latex语句并按下Alt &#xff08;此处以后补一张图&#xff09; 该方法不需要额外安装什么插件哦&#xff01;...

Google Play PolicyBytes 政策更新中文视频 | 2023 年 10 月

Google Play 持续帮助开发者开启成功出海之旅&#xff0c;为用户提供安全优质的应用。也感谢大家与我们携手合作&#xff0c;继续努力将 Google Play 打造为一个安全可信赖的平台。欢迎您观看 Google Play PolicyBytes 中文视频了解 2023 年 10 月政策更新内容&#xff0c;更及…...

pytorch-fastrcnn识别王者荣耀敌方英雄血条

文章目录 前言效果如下实现训练数据获得训练数据和测试数据yaml文件训练py画框文件的修改py测试py升级 前言 最近看王者荣耀视频看到了一个别人提供的一个百里自动设计解决方案,使用一个外设放在百里的二技能上,然后拖动外设在屏幕上滑动,当外设检测到有敌方英雄时外设自动松开…...

阿里云推出通义千问App,提供全方位的协助

&#x1f989; AI新闻 &#x1f680; 阿里云推出通义千问App&#xff0c;提供全方位的协助 摘要&#xff1a;阿里云旗下大模型通义千问App登陆各大安卓应用市场&#xff0c;具有超大规模预训练模型&#xff0c;可在创意文案、办公助理、学习助手、趣味生活等方面协助用户。功…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...