使用LLDB调试clang调用成员函数报address access protected错误如何解决
LLDB调试clang时调用成员函数触发SIGSEGV的问题原因及解决方案
问题原因
该差异来自LLDB和GDB的表达式求值默认安全策略、ABI解析逻辑的区别,具体原因分为两类:
- LLDB默认开启了内存访问保护限制,禁止表达式求值过程中访问只读代码段、低地址常量段等受保护的内存区域。而clang的
getIdentifier()这类成员函数内部会访问全局内置标识符池、常量表,刚好落在LLDB默认禁止访问的地址范围内,就会触发你收到的错误提示:
error: Execution was interrupted, reason: signal SIGSEGV: address access protected (fault address: 0x555555554000).
The process has been returned to the state before expression evaluation.
- LLDB的C++虚函数ABI解析、PIE程序重定位支持不如GDB完善。Debug版LLVM默认会生成位置无关(PIE)可执行文件,LLDB在表达式求值调用虚函数时,容易出现虚表地址重定位错误,跳转到受保护的地址段触发段错误。
解决方案
你可以按照优先级尝试以下方案:
- 方案1:修改LLDB运行时配置,关闭内存保护限制
启动LLDB后,在运行clang程序前执行以下两条配置命令,匹配GDB的默认表达式求值策略:
配置完成后再运行程序命中断点,即可直接用settings set target.protected-memory-workaround-enabled true settings set expr.jit-code-allow-write-execute trueprint FoundDecl->getIdentifier()正常调用成员函数。 - 方案2:使用带宽松参数的expression命令调用函数
如果方案1不生效,命中断点后不要用默认的print命令,改用以下命令调用成员函数:expression --no-validate -- FoundDecl->getIdentifier()--no-validate参数会跳过LLDB的类型校验逻辑,避免因为虚函数类型解析错误触发访问异常。 - 方案3:重新编译非PIE版本的LLVM/clang
如果前两个方案都无效,你可以在编译LLVM时追加-DCMAKE_POSITION_INDEPENDENT_CODE=OFF配置参数,关闭位置无关代码生成:
编译出的非PIE版本可执行文件不会存在LLDB重定位异常的问题,可以完全匹配GDB的调试体验。cmake -G Ninja ../llvm \ -DCMAKE_BUILD_TYPE=Debug \ -DLLVM_ENABLE_PROJECTS=clang \ -DCMAKE_POSITION_INDEPENDENT_CODE=OFF
内容的提问来源于stack exchange,提问作者parth_07
相关产品推荐
相关产品推荐

