如何利用Delphi映射文件定位Access Violation(AV)的根源?
Delphi Access Violation地址定位排查方案
问题场景
客户反馈AV报错:
Access violation at address 5053B2B2 in module 'ZZZZ.exe'. Read of address FFFFFFC4.
持有与客户版本一致的Delphi映射文件,构建时FinalBuilder设置的镜像基址为$5053FFEF,程序使用UPX压缩。映射文件头部节信息:
0001:50531000 05413280H .text CODE 0002:55945000 0002EADCH .itext ICODE 0003:55974000 0011A744H .data DATA 0004:55A8F000 000B41A0H .bss BSS 0005:00000000 00000154H .tls TLS 0006:50530000 00000000H .pdata PDATA
尝试计算5053B2B2 - 50531000 = $A2B2,但映射文件中无对应符号,无法定位报错点。
排查步骤
- 验证UPX压缩的影响:UPX会对PE文件进行压缩,运行时才会将代码解压到内存,这会导致内存加载地址与原始映射文件的基址不匹配。先使用未压缩的程序复现问题,或用UPX解压客户提供的
ZZZZ.exe后,再对比映射文件排查。 - 核对镜像基址的一致性:FinalBuilder设置的镜像基址
$5053FFEF与映射文件中.text节起始地址50531000存在矛盾,需确认:- 用PE查看工具(如PEview)打开构建后的exe,检查文件头的
ImageBase字段,确认是否与FinalBuilder设置的基址一致。 - 映射文件中
0001:50531000的线性地址,可通过线性地址 - ImageBase得到该节的RVA,再在映射文件中查找对应RVA的符号。
- 用PE查看工具(如PEview)打开构建后的exe,检查文件头的
- 修正地址计算逻辑:
- 确认报错地址归属:
5053B2B2处于.text节范围内(.text起始50531000,结束地址50531000 + 05413280 = 55944280)。 - 计算节内偏移:
5053B2B2 - 50531000 = $A2B2。 - 在映射文件的
.text节符号列表中,查找小于等于$A2B2的最大符号地址,该符号即为报错位置的邻近函数;若找不到,需检查映射文件是否包含完整符号。
- 确认报错地址归属:
- 确保映射文件完整性:构建时需在Delphi工程选项的Linker页面,勾选"Detailed map file"并选择"Include all symbols",生成包含所有符号的详细映射文件,否则无法精确定位局部代码或函数。
- 排查内存重定位情况:若程序加载时因内存冲突无法使用指定基址,Windows会自动重定位。让客户用Process Explorer查看
ZZZZ.exe的实际加载基址,通过报错地址 - 实际加载基址得到RVA,再去映射文件中匹配对应符号。
内容的提问来源于stack exchange,提问作者LandShark
相关产品推荐
相关产品推荐

