技术问询:函数/过程能否知晓自身运行的单元/模块并访问调试信息?
关于Delphi函数/过程获取自身单元/模块信息的问题
核心结论
可以实现,但需区分有无调试信息的场景,访问调试信息的方式依赖Delphi特定API或工具链。
一、无调试信息时获取模块信息
若程序未携带调试符号,函数/过程可通过Windows API获取当前所在模块(EXE或DLL)的路径,但无法直接获取单元名称:
- 调用
GetModuleHandle配合GetModuleFileName,能拿到当前执行代码所在模块的完整路径。 - 示例代码:
procedure GetCurrentModuleInfo; var hModule: HMODULE; szPath: array[0..MAX_PATH] of Char; begin hModule := GetModuleAddress(@GetCurrentModuleInfo); GetModuleFileName(hModule, szPath, MAX_PATH); // 将路径写入文本文件 with TFileStream.Create('module_info.txt', fmCreate or fmShareDenyWrite) do try Write(szPath[0], StrLen(szPath) * SizeOf(Char)); finally Free; end; end;
二、有调试信息时获取单元/源码关联信息
当EXE/DCU包含调试信息(编译时勾选"Include remote debug symbols"或生成MAP文件),可通过以下方式访问:
- 利用Delphi调试API:使用
TDebugInfoReader类(Delphi XE及以上版本提供),读取程序调试符号,解析当前函数对应的单元名称、源码路径等信息。 - 解析MAP文件:编译时生成MAP文件,函数内部读取该文件,通过当前指令地址匹配对应函数、单元信息。
- 示例思路(基于调试API):
uses System.SysUtils, System.Classes, Winapi.Windows, DebugInfoReader; procedure GetCurrentUnitInfo; var DebugReader: TDebugInfoReader; Address: Pointer; SymInfo: TSymbolInfo; FileStream: TFileStream; begin Address := @GetCurrentUnitInfo; DebugReader := TDebugInfoReader.Create(GetModuleHandle(nil)); try if DebugReader.GetSymbolInfo(Address, SymInfo) then begin // SymInfo.UnitName 即为所在单元名称 // 将信息写入文件 FileStream := TFileStream.Create('unit_info.txt', fmCreate or fmShareDenyWrite); try FileStream.WriteBuffer(PChar(SymInfo.UnitName)^, Length(SymInfo.UnitName) * SizeOf(Char)); finally FileStream.Free; end; end; finally DebugReader.Free; end; end;
注意事项
- 调试信息仅在编译时开启相关选项后才会包含在EXE/DCU中,发布版通常会移除这些信息,此时无法获取单元等源码关联信息。
- 直接访问调试信息的操作性能较低,不建议在高频执行的代码中使用。
内容的提问来源于stack exchange,提问作者Error - CPU Not Foud
相关产品推荐
相关产品推荐

