MSVC 中的 Address Sanitizer:为什么启动时报错?
Address Sanitizer in MSVC: why does it report an error on startup?
我正在尝试一个将 Qt 与 MSVC 2019 和 Address Sanitizer 结合使用的项目。我用 Address Sanitizer 构建了项目,但没有重建所有库,包括 Qt。
它在资源初始化时在 Qt 内部崩溃(在调用堆栈中有 qRegisterResourceData
)。
这是:
- 滥用地址清理器,比如,我也应该用它重建 Qt DLL 吗?
- 我应该深入研究 Qt 中的一个问题?
- 已知的 Qt 问题?
我在 Wizard 默认创建的 Widget 应用程序中重现了这个问题。调用栈如下:
> KernelBase.dll!RaiseException() Unknown
QtWidgetsApplication1.exe!__vcasan::OnAsanReport(const char * description, const char * report, bool __throw) Line 602 C++
QtWidgetsApplication1.exe!__vcasan::ReportCallback(const char * szReport) Line 325 C++
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::ScopedInErrorReport::~ScopedInErrorReport(void) Unknown
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::ReportMallocUsableSizeNotOwned(unsigned __int64,struct __sanitizer::BufferedStackTrace *) Unknown
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::asan_malloc_usable_size(void const *,unsigned __int64,unsigned __int64) Unknown
clang_rt.asan_dbg_dynamic-x86_64.dll!_recalloc() Unknown
ucrtbased.dll!_register_onexit_function::__l2::<lambda>() Line 112 C++
ucrtbased.dll!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) &,void <lambda>(void)>(__acrt_lock_and_call::__l2::void <lambda>(void) && setup, _register_onexit_function::__l2::int <lambda>(void) & action, __acrt_lock_and_call::__l2::void <lambda>(void) && cleanup) Line 204 C++
ucrtbased.dll!__acrt_lock_and_call<int <lambda>(void)>(const __acrt_lock_id lock_id, _register_onexit_function::__l2::int <lambda>(void) && action) Line 980 C++
ucrtbased.dll!_register_onexit_function(_onexit_table_t * table, int(*)() function) Line 149 C++
Qt5Cored.dll!_onexit(int(*)() function) Line 267 C++
Qt5Cored.dll!atexit(void(*)() function) Line 275 C++
Qt5Cored.dll!QPropertyAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) Line 268 C++
Qt5Cored.dll!QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) Line 991 C++
Qt5Cored.dll!QAbstractAnimation::start(QAbstractAnimation::DeletionPolicy policy) Line 1362 C++
Qt5Widgetsd.dll!QWidgetAnimator::animate(QWidget * widget, const QRect & _final_geometry, bool animate) Line 114 C++
Qt5Widgetsd.dll!QToolBarAreaLayout::apply(bool animate) Line 936 C++
Qt5Widgetsd.dll!QMainWindowLayoutState::apply(bool animated) Line 687 C++
Qt5Widgetsd.dll!QMainWindowLayout::applyState(QMainWindowLayoutState & newState, bool animate) Line 2759 C++
Qt5Widgetsd.dll!QMainWindowLayout::setGeometry(const QRect & _r) Line 1979 C++
Qt5Widgetsd.dll!QLayoutPrivate::doResize() Line 596 C++
Qt5Widgetsd.dll!QLayout::activate() Line 1119 C++
Qt5Widgetsd.dll!QWidgetPrivate::setVisible(bool visible) Line 8083 C++
Qt5Widgetsd.dll!QWidget::setVisible(bool visible) Line 8044 C++
Qt5Widgetsd.dll!QWidget::show() Line 7670 C++
QtWidgetsApplication1.exe!main(int argc, char * * argv) Line 9 C++
QtWidgetsApplication1.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 97 C++
QtWidgetsApplication1.exe!invoke_main() Line 107 C++
QtWidgetsApplication1.exe!__scrt_common_main_seh() Line 288 C++
QtWidgetsApplication1.exe!__scrt_common_main() Line 331 C++
QtWidgetsApplication1.exe!WinMainCRTStartup(void * __formal) Line 17 C++
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
输出:
Address 0x01c416f8eda0 is a wild pointer.
SUMMARY: AddressSanitizer: bad-malloc_usable_size (C:\Program Files (x86)\Microsoft Visual Studio19\Professional\VC\Tools\MSVC.29.30133\bin\HostX86\x64\clang_rt.asan_dbg_dynamic-x86_64.dll+0x18004e63a) in _asan_wrap_GlobalSize+0x4b948
Address Sanitizer Error: bad-malloc_usable_size
问题是加载订单。
Qt 恰好在 ASan 之前加载并且在 ASan DLL 加载之前加载 C/C++ 运行时。 Qt 执行一些初始化。因此,内存在 ASan 不知情的情况下被 malloc
编辑,后来 ASan 在没有事先 malloc
的情况下看到 realloc
,它报告了这一点。
使用 ASan 构建 Qt 应该可以解决问题,我还没有尝试过,因为我找到了一个不涉及 Qt 重建的解决方法。
解决方法:只需让 Qt DLL 导入 ASan DLL。对我来说是通过以下命令:
setdll /d:clang_rt.asan_dbg_dynamic-x86_64.dll <path_to_deployed_debug_app>\Qt5Cored.dll
setdll /d:clang_rt.asan_dynamic-x86_64.dll <path_to_deployed_release_app>\Qt5Core.dll
setdll
是 Detours 库中的一个工具,可以从 https://github.com/microsoft/Detours 获得,然后使用 nmake
.
构建
clang_rt.asan_dynamic-x86_64.dll
和 clang_rt.asan_dbg_dynamic-x86_64.dll
应该直接可用或从 %path%
执行此命令时,最方便的方法是从 VS 工具命令提示符执行命令。
我正在尝试一个将 Qt 与 MSVC 2019 和 Address Sanitizer 结合使用的项目。我用 Address Sanitizer 构建了项目,但没有重建所有库,包括 Qt。
它在资源初始化时在 Qt 内部崩溃(在调用堆栈中有 qRegisterResourceData
)。
这是:
- 滥用地址清理器,比如,我也应该用它重建 Qt DLL 吗?
- 我应该深入研究 Qt 中的一个问题?
- 已知的 Qt 问题?
我在 Wizard 默认创建的 Widget 应用程序中重现了这个问题。调用栈如下:
> KernelBase.dll!RaiseException() Unknown
QtWidgetsApplication1.exe!__vcasan::OnAsanReport(const char * description, const char * report, bool __throw) Line 602 C++
QtWidgetsApplication1.exe!__vcasan::ReportCallback(const char * szReport) Line 325 C++
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::ScopedInErrorReport::~ScopedInErrorReport(void) Unknown
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::ReportMallocUsableSizeNotOwned(unsigned __int64,struct __sanitizer::BufferedStackTrace *) Unknown
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::asan_malloc_usable_size(void const *,unsigned __int64,unsigned __int64) Unknown
clang_rt.asan_dbg_dynamic-x86_64.dll!_recalloc() Unknown
ucrtbased.dll!_register_onexit_function::__l2::<lambda>() Line 112 C++
ucrtbased.dll!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) &,void <lambda>(void)>(__acrt_lock_and_call::__l2::void <lambda>(void) && setup, _register_onexit_function::__l2::int <lambda>(void) & action, __acrt_lock_and_call::__l2::void <lambda>(void) && cleanup) Line 204 C++
ucrtbased.dll!__acrt_lock_and_call<int <lambda>(void)>(const __acrt_lock_id lock_id, _register_onexit_function::__l2::int <lambda>(void) && action) Line 980 C++
ucrtbased.dll!_register_onexit_function(_onexit_table_t * table, int(*)() function) Line 149 C++
Qt5Cored.dll!_onexit(int(*)() function) Line 267 C++
Qt5Cored.dll!atexit(void(*)() function) Line 275 C++
Qt5Cored.dll!QPropertyAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) Line 268 C++
Qt5Cored.dll!QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) Line 991 C++
Qt5Cored.dll!QAbstractAnimation::start(QAbstractAnimation::DeletionPolicy policy) Line 1362 C++
Qt5Widgetsd.dll!QWidgetAnimator::animate(QWidget * widget, const QRect & _final_geometry, bool animate) Line 114 C++
Qt5Widgetsd.dll!QToolBarAreaLayout::apply(bool animate) Line 936 C++
Qt5Widgetsd.dll!QMainWindowLayoutState::apply(bool animated) Line 687 C++
Qt5Widgetsd.dll!QMainWindowLayout::applyState(QMainWindowLayoutState & newState, bool animate) Line 2759 C++
Qt5Widgetsd.dll!QMainWindowLayout::setGeometry(const QRect & _r) Line 1979 C++
Qt5Widgetsd.dll!QLayoutPrivate::doResize() Line 596 C++
Qt5Widgetsd.dll!QLayout::activate() Line 1119 C++
Qt5Widgetsd.dll!QWidgetPrivate::setVisible(bool visible) Line 8083 C++
Qt5Widgetsd.dll!QWidget::setVisible(bool visible) Line 8044 C++
Qt5Widgetsd.dll!QWidget::show() Line 7670 C++
QtWidgetsApplication1.exe!main(int argc, char * * argv) Line 9 C++
QtWidgetsApplication1.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 97 C++
QtWidgetsApplication1.exe!invoke_main() Line 107 C++
QtWidgetsApplication1.exe!__scrt_common_main_seh() Line 288 C++
QtWidgetsApplication1.exe!__scrt_common_main() Line 331 C++
QtWidgetsApplication1.exe!WinMainCRTStartup(void * __formal) Line 17 C++
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
输出:
Address 0x01c416f8eda0 is a wild pointer.
SUMMARY: AddressSanitizer: bad-malloc_usable_size (C:\Program Files (x86)\Microsoft Visual Studio19\Professional\VC\Tools\MSVC.29.30133\bin\HostX86\x64\clang_rt.asan_dbg_dynamic-x86_64.dll+0x18004e63a) in _asan_wrap_GlobalSize+0x4b948
Address Sanitizer Error: bad-malloc_usable_size
问题是加载订单。
Qt 恰好在 ASan 之前加载并且在 ASan DLL 加载之前加载 C/C++ 运行时。 Qt 执行一些初始化。因此,内存在 ASan 不知情的情况下被 malloc
编辑,后来 ASan 在没有事先 malloc
的情况下看到 realloc
,它报告了这一点。
使用 ASan 构建 Qt 应该可以解决问题,我还没有尝试过,因为我找到了一个不涉及 Qt 重建的解决方法。
解决方法:只需让 Qt DLL 导入 ASan DLL。对我来说是通过以下命令:
setdll /d:clang_rt.asan_dbg_dynamic-x86_64.dll <path_to_deployed_debug_app>\Qt5Cored.dll
setdll /d:clang_rt.asan_dynamic-x86_64.dll <path_to_deployed_release_app>\Qt5Core.dll
setdll
是 Detours 库中的一个工具,可以从 https://github.com/microsoft/Detours 获得,然后使用 nmake
.
clang_rt.asan_dynamic-x86_64.dll
和 clang_rt.asan_dbg_dynamic-x86_64.dll
应该直接可用或从 %path%
执行此命令时,最方便的方法是从 VS 工具命令提示符执行命令。