我正在尝试用我的项目来构建
g++ -O0 -g -fsanitize=address -fno-omit-frame-pointer
Run Code Online (Sandbox Code Playgroud)
但是会遇到很多错误:
/home/user/libs/opencv/include/opencv2/core/mat.hpp:715: undefined reference to `__asan_report_load8'
Run Code Online (Sandbox Code Playgroud)
如何使用AddressSanitize支持编译项目?
我的gcc版本是4.8.4.
最新版本的GCC和Clang具有Undefined Behavior Sanitizer(UBSan),它是一个编译标志(-fsanitize=undefined
),用于添加运行时检测代码.出现错误时,会显示如下警告:
packet-ber.c:1917:23:运行时错误:左移54645397829836991 8个位置无法在类型'long int'中表示
现在我想调试它并在所述行上获得调试中断.对于Address Sanitizer(ASAN),会ASAN_OPTIONS=abort_on_error=1
导致可捕获的致命错误.唯一可用的UBSan选项会UBSAN_OPTIONS=print_stacktrace=1
导致报告的调用跟踪转储.但是,这不允许我检查局部变量然后继续该程序.使用的-fsanitize-undefined-trap-on-error
,因此不可能的.
我应该如何在UBSan报告中打破gdb?虽然break __sanitizer::SharedPrintfCode
似乎有效,但这个名字看起来很内部.
我只是尝试用GCC和-fsanitize=address
旗帜进行编译.当我运行我的程序时,地址清理程序发现了一个缺陷,但堆栈跟踪没有帮助.如何配置它以使其指向我需要查看的源代码位置?
=================================================================
==32415== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6006004b38a0 at pc 0x10b136d5c bp 0x7fff54b8e5d0 sp 0x7fff54b8e5c8
WRITE of size 8 at 0x6006004b38a0 thread T0
#0 0x10b136d5b (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1000c6d5b)
#1 0x10b136e0c (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1000c6e0c)
#2 0x10b138ef5 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1000c8ef5)
#3 0x10b137a2e (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1000c7a2e)
#4 0x10b13acf2 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1000cacf2)
#5 0x10b253647 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001e3647)
#6 0x10b24ee55 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001dee55)
#7 0x10b237108 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001c7108)
#8 0x10b237c17 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001c7c17)
#9 0x10b2385c9 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001c85c9)
#10 0x10b23f659 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001cf659)
#11 0x10b254951 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001e4951)
#12 0x10b24fbeb (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001dfbeb)
#13 0x10b23dc38 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001cdc38)
#14 0x10b229d28 (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001b9d28)
#15 0x10b229bda (/Users/cls/workspace/NetworKit/./NetworKit-Tests-D+0x1001b9bda)
#16 0x7fff8b7785fc (/usr/lib/system/libdyld.dylib+0x35fc)
#17 0x2
0x6006004b38a0 …
Run Code Online (Sandbox Code Playgroud) 我想在OSX Mountain Lion上使用clang address sanitizer,因为Valgrind在这个平台上有内存检查问题.但是当我-fsanitize=address
在编译期间(就像我在这个页面上看到的那样:http://clang.llvm.org/docs/AddressSanitizer.html)时,我收到了这个错误:clang: error: argument unused during compilation: '-fsanitize=address'
所以,我的问题是如何在OS X上使用Clang Address Sanitizer?如果我不能使用它,我可以使用哪种工具?
我有Xcode的下载文件,它是最新的.(也许这个版本没有用它来解决消毒剂的问题)
我想要一些工具来诊断用户免费后的错误和未初始化的错误.我正在考虑Sanitizer(记忆和/或地址)和Valgrind.但我对它们的优点和缺点一无所知.谁能说出Sanitizer和Valgrind的主要特征,差异和优缺点?
编辑:我发现了一些比较:Valgrind使用DBI(动态二进制检测),Sanitizer使用CTI(编译时检测).无论Sanitizer的运行速度比Valgrind(2x)快得多,Valgrind都能让程序慢得多(20倍).如果有人能给我一些更重要的要点,那将是一个很大的帮助.
我添加了AddressSanitizer标志如下:
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
Run Code Online (Sandbox Code Playgroud)
一切都在使用时构建并运行良好Unix Makefiles
.
生成Xcode项目时出现问题,它只是不想链接,因为它找不到ASan库.
我已经找到了两个解决方案,但决定不使用它们,因为它们不能仅使用CMake自动化:
-Wl,-undefined,dynamic_lookup
到链接的标志,因此它会跳过链接到动态库.libclang_rt.asan_osx_dynamic.dylib
直接链接.那么这两种解决方案的问题是什么?
DYLD_INSERT_LIBRARIES
指向的环境变量libclang_rt.asan_osx_dynamic.dylib
.另外作为另一种解决方案,我尝试从Xcode目标方案启用Address Sanitizer标志,但有趣的是它没有检测到我添加的问题,因此我没有将其列为解决方案,因为它未通过我的测试.
任何帮助都感激不尽.
在Ubuntu 14.10上,llvm-symbolizer
程序安装为/usr/bin/llvm-symbolizer-3.5
.通常情况下,地址消毒剂希望找到一个名为二进制llvm-symbolizer
在PATH
.但是,作为一种解决方法,可以明确设置ASAN_SYMBOLIZER_PATH
.因此,ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.5
在环境中设置会让地址清理程序检测程序打印符号化错误.
在Ubuntu 16.04上,llvm-symbolizer
程序再次安装了版本后缀,现在为/usr/bin/llvm-symbolizer-3.8
.但是,ASAN_SYMBOLIZER_PATH
设置似乎不再起作用.ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.8
当ASAN检测到错误时,在环境中运行带有set 的ASAN检测程序会生成以下错误:
==18718==ERROR: External symbolizer path is set to '/usr/bin/llvm-symbolizer-3.8' which isn't a known symbolizer. Please set the path to the llvm-symbolizer binary or other known tool.
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么这种行为改变了,或者如何恢复旧的行为?这似乎是不合理的限制.我指向ASAN的符号化程序绝对是一个已知的符号化器,它恰好在最后有一个Ubuntu强制版本标签.
请注意,调整PATH
在这里没有用,因为Ubuntu不提供没有llvm-symbolizer
版本装饰的二进制文件.
我的项目包括一个大型C++库和Python绑定(通过Boost.Python).测试套件主要是在Python绑定之上编写的,我想用清理程序运行它,从ASAN开始.
我正在运行macOS(10.13.1 FWIW,但我也遇到了以前版本的问题),我似乎找不到在Python模块上运行ASAN的方法(我非常怀疑这与Boost.Python有关) ,我想它与其他技术一样).
这是一个简单的Python模块:
// hello_ext.cc
#include <boost/python.hpp>
char const* greet()
{
auto* res = new char[100];
std::strcpy(res, "Hello, world!");
delete [] res;
return res;
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
Run Code Online (Sandbox Code Playgroud)
这是我使用的Makefile,为MacPorts制作:
// Makefile
CXX = clang++-mp-4.0
CXXFLAGS = -g -std=c++14 -fsanitize=address -fno-omit-frame-pointer
CPPFLAGS = -isystem/opt/local/include $$($(PYTHON_CONFIG) --includes)
LDFLAGS = -L/opt/local/lib
PYTHON = python3.5
PYTHON_CONFIG = python3.5-config
LIBS = -lboost_python3-mt $$($(PYTHON_CONFIG) --ldflags)
all: hello_ext.so
hello_ext.so: hello_ext.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $< $(LIBS)
check: …
Run Code Online (Sandbox Code Playgroud) Uccntu构建的gcc-6.2((Ubuntu 6.2.0-3ubuntu11~16.04)6.2.0 20160901)不再存在这个问题.
我使用了Ubuntu建立GCC-6.1的[1]((Ubuntu的6.1.1-3ubuntu11〜14.04.1)6.1.1 20160511),GNU binutils的2.24,和libstdc ++与GLIBCXX_3.4.22支持.即使在简单的"hello world"程序中,指定清洁剂也不会强制使用黄金链接器.
#include <iostream>
int main() {
std::cout << "Hello, world!\n";
}
Run Code Online (Sandbox Code Playgroud)
编译和链接
g++ -fsanitize=address -c -o main main.cpp
g++ -fsanitize=address -o main main.o
Run Code Online (Sandbox Code Playgroud)
给出了错误
/usr/bin/ld: unrecognized option '--push-state'
/usr/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
这表示该-fsanitize
选项未选择黄金链接器.当然,简单的解决方法是-fuse-ld=gold
在链接期间使用,但是在使用消毒剂时,gcc的先前版本不需要这样做.例如,这个代码在gcc-5.3和4.9下完全正常(两者都是Ubuntu版本).是否有其他人在使用非Ubuntu构建的gcc-6.1时遇到此问题?Ubuntu构建是否破损?
[1]使用以下标志构建(gcc-5.3和gcc-4.9的构建只有名称和后缀的差异)
--with-pkgversion='Ubuntu 6.1.1-3ubuntu11~14.04.1'
--with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs
--enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++
--prefix=/usr
--program-suffix=-6
--enable-shared
--enable-linker-build-id
--libexecdir=/usr/lib
--without-included-gettext
--enable-threads=posix
--libdir=/usr/lib
--enable-nls
--with-sysroot=/
--enable-clocale=gnu
--enable-libstdcxx-debug
--enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=gcc4-compatible
--disable-libstdcxx-dual-abi
--enable-gnu-unique-object
--disable-vtable-verify
--enable-libmpx …
Run Code Online (Sandbox Code Playgroud) 这是悬空指针|参考示例:
#include <string>
#include <string_view>
#include <iostream>
std::string foo() {
return "test";
}
int main() {
std::string_view bar = foo(); // bar is pointed to destructed string
std::cout << bar << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
地址清理程序无法捕获它,至少使用默认选项.是否有可能通过地址消毒剂捕获此类错误?
UPD.
报告了这个bug:
c++ ×5
clang ×3
gcc ×3
sanitizer ×3
boost-python ×1
c ×1
c++17 ×1
cmake ×1
gdb ×1
gold-linker ×1
ld ×1
macos ×1
memory ×1
python ×1
stack-trace ×1
ubsan ×1
ubuntu ×1
ubuntu-16.04 ×1
valgrind ×1