程序异常的堆栈查看

文章讲述了在程序出现异常时,使用Windbg进行调试时可能无法看到正确的堆栈信息,因为已经进入了异常处理的上下文。作者提供了使用.exr命令来查看异常记录,并通过.kbn命令恢复到异常前的上下文,以正确分析调用堆栈。示例中提到程序因调用无效的dll函数地址导致崩溃,强调了在调用dll函数时应确保地址非空的重要性。

当程序异常时,使用windbg查看可能会看不到正确的堆栈,例如

     ntdll!NtGetContextThread+0xc    C/C++/ASM
>    OperateFile!Content::copy_data+0x4c4     C/C++/ASM
     ntdll!LdrpDecrementModuleLoadCountEx+0x3d    C/C++/ASM
     ntdll!LdrUnloadDll+0x4d    C/C++/ASM
     KERNELBASE!FreeLibrary+0x16    C/C++/ASM
     dbgcore!WriteMiscInfo+0x324    C/C++/ASM
     dbgcore!WriteDumpData+0x1f7    C/C++/ASM
     dbgcore!MiniDumpProvideDump+0x46c    C/C++/ASM
     dbgcore!MiniDumpWriteDump+0x1dd    C/C++/ASM
     Base+0x54533    C/C++/ASM
     Base+0x53e67    C/C++/ASM
     Base+0x585fc    C/C++/ASM
     KERNELBASE!UnhandledExceptionFilter+0x1a0    C/C++/ASM
     ntdll!__RtlUserThreadStart+0x3a10b    C/C++/ASM
     ntdll!_RtlUserThreadStart+0x1b    C/C++/ASM
        

这里看到的是异常发生后的堆栈,异常的处理,是一个异常处理的上下文。 

原先的上下文被保存,直接切换成了异常的上下文。因此在使用windbg查看的时候,需要使用如下的命令切换到异常前的上下文:

.exr -1

The .exr command displays the contents of an exception record.

然后kbn查看,显示如下:

00 00b5f01c 0062e955 00e81bc8 ce091c9e 00000000 0x0
01 00b5f24c 0066ac7b 00e81bc8 0067712d ffffffff OperateFile!OperateFile::JumpUrl2+0xc5 [c:\OperateFile\OperateFile.cpp @ 1046] 
02 00b5fb10 006763c4 00000005 00deb038 00000000 OperateFile!main+0xa8b [c:\OperateFile\main.cpp @ 118] 
03 00b5fb44 00675605 005f0000 00000000 00dc485e OperateFile!WinMain+0xe4
04 (Inline) -------- -------- -------- -------- OperateFile!invoke_main+0x1a [d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 102] 
05 00de1128 00000000 00000001 a3daa3c1 00000020 OperateFile!__scrt_common_main_seh+0xf8 [d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 
 

可以看到最后调用了0地址,导致崩溃,查看实际代码,是加载dll,并后获取地址func并调用,结果func是空,未做检查直接调用导致崩溃。 

### 如何查看异常堆栈跟踪 在 Linux 系统中,当尝试通过 `gdb` 或 `strace` 这类工具附加到进程中时,可能会遇到权限不足的问题,表现为错误提示 “ptrace attach Operation not permitted”。这是由于目标进程的安全设置阻止了外部调试器的访问[^1]。 对于 Java 应用程序而言,可以利用专门设计用于诊断 JVM 和应用程序行为的工具来获取线程堆栈信息以及异常堆栈跟踪: #### 工具介绍 - **`jstack`**: 该命令能够直接显示指定 Java 进程中的线程堆栈信息。它适用于分析死锁、性能瓶颈等问题。 ```bash jstack <PID> ``` 上述命令会输出当前运行的所有线程及其对应的堆栈信息[^2]。 - **`jmap`**: 此外还可以借助 `jmap` 查看内存分配状况并导出完整的堆转储文件以便进一步离线分析。 ```bash jmap -dump:live,format=b,file=heap.bin <PID> ``` 如果发现某些地方存在未妥善处理的异常,则需重新审视代码逻辑是否存在如下情形之一: 1. 被捕获后的异常仅记录日志而缺乏实际修复措施; 2. 利用关键字 throw/throws 将责任转移给上级函数却依旧无人接手解决;这两种做法均属于变相忽视潜在风险的行为[^3]。 针对上述提到的日志管理部分,建议采用结构化的方式存储数据(如 JSON 格式),这样不仅便于后续检索而且有助于实现自动化监控报警机制建设工作。 ```python import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') def divide(a,b): try: result = a / b except ZeroDivisionError as e: logging.error(f"Zero Division Error Occurred:{e}", exc_info=True) divide(10,0) ``` 以上 Python 示例展示了如何正确配置 logger 并且演示了一个简单的除法运算场景下发生零分母错误时应该如何操作——即除了简单地打印消息之外还应附带完整的 traceback 记录下来供日后审查之用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值