安装程序:Windows 10、Clang 16.0.3、ASan(-fsanitize=address
)、-O0
任何与处理异常相关的代码,例如try/catch,都会导致关于访问违规的报告(另外,undefined
sanitazation也不会对此感到高兴),或者会改变程序的行为。
#include <stdexcept>
#include <iostream>
int main() {
try {
throw std::runtime_error("test");
} catch (const std::runtime_error &ex) {
std::cout << ex.what() << std::endl;
}
return 0;
}
字符串
任何与此列表const std::runtime_error &ex
,const std::runtime_error ex
,std::runtime_error &ex
,std::runtime_error ex
结果不同的结果都是某种不良行为。const std::runtime_error &ex
、const std::runtime_error ex
直接导致如下错误报告:
==4384==ERROR: AddressSanitizer: access-violation on unknown address 0x00000000000e (pc 0x7ff74e3d12ca bp 0x008e4edcfaf0 sp 0x008e4edcd7f0 T0)
==4384==The signal is caused by a READ memory access.
==4384==Hint: address points to the zero page.
#0 0x7ff74e3d12c9 in main C:\projects\test\asan.cpp:8
#1 0x7ff74e478ccf in _CallSettingFrame d:\a01\_work\6\s\src\vctools\crt\vcruntime\src\eh\amd64\handlers.asm:49
#2 0x7ff74e46e6bb in __FrameHandler3::CxxCallCatchBlock(struct _EXCEPTION_RECORD *) d:\a01\_work\6\s\src\vctools\crt\vcruntime\src\eh\frame.cpp:1521
#3 0x7fffdfbb1715 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800a1715)
#4 0x7ff74e3d113b in main C:\projects\test\asan.cpp:6
#5 0x7ff74e435d6b in invoke_main d:\a01\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
#6 0x7ff74e435d6b in __scrt_common_main_seh d:\a01\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#7 0x7fffdf757613 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017613)
#8 0x7fffdfb626b0 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526b0)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: access-violation C:\projects\test\asan.cpp:8 in main
==4384==ABORTING
型
而std::runtime_error &ex
、std::runtime_error ex
的行为发生了改变,并且会包含一些带有潜在错误报告的乱码:
HГ─@]├HН♣▌f
=================================================================
==23388==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7ff72ef69186 in thread T0
#0 0x7ff72eed1e1d in free C:\src\llvm_package_16.0.3\llvm-project\compiler-rt\lib\asan\asan_malloc_win.cpp:82
Address 0x7ff72ef69186 is a wild pointer inside of access range of size 0x000000000001.
SUMMARY: AddressSanitizer: bad-free C:\src\llvm_package_16.0.3\llvm-project\compiler-rt\lib\asan\asan_malloc_win.cpp:82 in free
==23388==ABORTING
型
我花了很多时间试图找到错误的来源,但没有找到任何东西。唯一的线索是,编译时不进行地址清理可以修复所有问题。
1条答案
按热度按时间3pmvbmvn1#
google/sanitizers
中有一个对应的issue #749,它是LLVM Sanitizer的所在地。建议的解决方法是
将
__attribute__((no_sanitize_address))
应用于使用EH的每个函数,如果您的应用程序在正常操作中不使用EH,则可以正常工作。但这就违背了净化的目的,所以稍微好一点的解决方法是将try/catch Package 在lambda表达式中并立即调用它。这样做的好处是,我们可以将
__attribute__((no_sanitize_address))
专门应用于代码的这一部分,从而限制影响:字符串
现在,让我们通过定义一个实现相同功能的宏来使它更美观
型
但是我们也不要忘记,当用ASan编译时,这只会在windows上失败
型
Aaaand让我们通过允许lambda隐式地通过引用捕获变量来使它更无缝地使用+引用问题似乎是一个很好的实践
型
最后我们可以这样使用:
型
并且异常处理没有任何问题,万岁!
注意:当使用
TRY_CATCH_WRAPPER
时,{}
是不必要的,因为代码已经 Package 在宏内部的{}
中,但它更适合clang-format,所以我使用它。