如何为多个 C++ 二进制文件启用地址清理器
How to enable address sanitizer for multiple C++ binaries
我正在开发一种由多个 C++ 可执行文件和库组成的产品,这些文件和库之间存在各种依赖关系。我正在使用 GCC 和 -fsanitize-address
构建它们。
据我了解,如果我想将地址清理器与库一起使用,我必须将其构建为共享对象(这是 GCC 的默认选项)。因此,我认为最好的选择是使用 -static-libasan
为可执行文件静态构建地址清理器,并为库动态构建它。但是,当我这样做时,在构建一个 C++ 可执行文件时出现 link 错误:
==10823==Your application is linked against incompatible ASan runtimes
这让我觉得地址清理器的静态和动态版本不能与 GCC 混合使用,对吗?我无法在消毒剂 GitHub 页面上找到任何相关信息。
TLDR:
- 如果您使用 GCC/Clang 并且主要可执行文件和 shlib 都经过清理,则您不需要做任何特别的事情 - 只需坚持默认
-fsanitize=address
.
- 如果您使用 GCC 并且仅清理 shlib,请再次继续使用
-fsanitize=address
并在 运行 您的应用程序时另外导出 LD_PRELOAD=$(gcc -print-file-name=libasan.so)
。
- 如果您使用 Clang 并且仅对 shlib 进行清理,compile/link 使用
-fsanitize-address -shared-libasan
并在 运行 应用程序时另外导出 LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so)
。
现在进行一些解释。最初 Asan 仅存在于 Clang 中,默认情况下使用(并且仍在使用)-static-libasan
。当它被移植到 GCC 时,GCC 开发人员决定共享运行时是首选(例如,因为它允许一个人只清理一个共享库并保持主要可执行文件未清理,例如清理 Python 模块而不重新编译 python.exe,参见 wiki 其他例子)。这两种方法都是二进制不兼容的,因此您不能 link 应用程序的一部分使用静态运行时而部分使用动态运行时。
大致
- GCCs
-fsanitize=address
等同于 Clangs -fsanitize=address -shared-libasan
(并且 -shared-libasan
是 Clang 中的第二个 class 公民,因此不受支持)
- Clangs
-fsanitize=address
等同于 GCC -fsanitize=address -static-libasan
(同样,-static-libasan
是 GCC 中的第二 class 公民,因此有一些 issues)
作为旁注,其他 GCC/Clang 牙山差异见 this helpful wiki。
我正在开发一种由多个 C++ 可执行文件和库组成的产品,这些文件和库之间存在各种依赖关系。我正在使用 GCC 和 -fsanitize-address
构建它们。
据我了解,如果我想将地址清理器与库一起使用,我必须将其构建为共享对象(这是 GCC 的默认选项)。因此,我认为最好的选择是使用 -static-libasan
为可执行文件静态构建地址清理器,并为库动态构建它。但是,当我这样做时,在构建一个 C++ 可执行文件时出现 link 错误:
==10823==Your application is linked against incompatible ASan runtimes
这让我觉得地址清理器的静态和动态版本不能与 GCC 混合使用,对吗?我无法在消毒剂 GitHub 页面上找到任何相关信息。
TLDR:
- 如果您使用 GCC/Clang 并且主要可执行文件和 shlib 都经过清理,则您不需要做任何特别的事情 - 只需坚持默认
-fsanitize=address
. - 如果您使用 GCC 并且仅清理 shlib,请再次继续使用
-fsanitize=address
并在 运行 您的应用程序时另外导出LD_PRELOAD=$(gcc -print-file-name=libasan.so)
。 - 如果您使用 Clang 并且仅对 shlib 进行清理,compile/link 使用
-fsanitize-address -shared-libasan
并在 运行 应用程序时另外导出LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so)
。
现在进行一些解释。最初 Asan 仅存在于 Clang 中,默认情况下使用(并且仍在使用)-static-libasan
。当它被移植到 GCC 时,GCC 开发人员决定共享运行时是首选(例如,因为它允许一个人只清理一个共享库并保持主要可执行文件未清理,例如清理 Python 模块而不重新编译 python.exe,参见 wiki 其他例子)。这两种方法都是二进制不兼容的,因此您不能 link 应用程序的一部分使用静态运行时而部分使用动态运行时。
大致
- GCCs
-fsanitize=address
等同于 Clangs-fsanitize=address -shared-libasan
(并且-shared-libasan
是 Clang 中的第二个 class 公民,因此不受支持) - Clangs
-fsanitize=address
等同于 GCC-fsanitize=address -static-libasan
(同样,-static-libasan
是 GCC 中的第二 class 公民,因此有一些 issues)
作为旁注,其他 GCC/Clang 牙山差异见 this helpful wiki。