最新版本的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
似乎有效,但这个名字看起来很内部.
我想在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的下载文件,它是最新的.(也许这个版本没有用它来解决消毒剂的问题)
我在 Ubuntu 20.04 LTS 上使用 clang++ 10,-fsanitize-undefined-trap-on-error -fsanitize=address,undefined,nullability,implicit-integer-truncation,implicit-integer-arithmetic-value-change,implicit-conversion,integer
我的代码正在生成随机字节
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<uint8_t> dd(0, 255);
...
ch = uint8_t(dd(gen));
Run Code Online (Sandbox Code Playgroud)
最后一行导致消毒程序报告未定义的行为位于bits/random.tcc中
template<...> void mersenne_twister_engine<...>::
_M_gen_rand(void) {
const _UIntType __upper_mask = (~_UIntType()) << __r;
const _UIntType __lower_mask = ~__upper_mask;
for (size_t __k = 0; __k < (__n - __m); ++__k)
{
_UIntType __y = ((_M_x[__k] & __upper_mask)
| (_M_x[__k + 1] & __lower_mask));
_M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1)
^ ((__y & 0x01) ? __a : 0)); …
Run Code Online (Sandbox Code Playgroud) Clang有各种消毒剂,可以在运行时开启以解决问题.
但是,有一些消毒剂我不能一起使用.这是为什么?
clang++-3.9 -std=c++1z -g -fsanitize=memory -fsanitize=address -o main main.cpp 1
clang: error: invalid argument '-fsanitize=address' not allowed with '-fsanitize=memory'
Run Code Online (Sandbox Code Playgroud)
这不是什么大问题,但是当我运行单元测试时,它需要的时间比它应该的长,因为我为相同的测试创建了多个二进制文件,并分别运行它们.
clang++-3.9 -std=c++1z -g -fsanitize=address -o test1 test.cpp
clang++-3.9 -std=c++1z -g -fsanitize=memory -fsanitize=undefined -o test2 test.cpp
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:
我很抱歉,如果这是一个超级简单的概念,但我发现很难获得正确的心态,以便正确使用由提供的消毒剂clang
.
float foo(float f) { return (f / 0); }
Run Code Online (Sandbox Code Playgroud)
我编译这个小片段
clang++ -fsanitize=float-divide-by-zero -std=c++11 -stdlib=libc++ -c source.cpp -o osan
Run Code Online (Sandbox Code Playgroud)
而且我还在不使用消毒剂的情况下编译了我的对象的"正常"版本
clang++ -std=c++11 -stdlib=libc++ -c source.cpp -o onorm
Run Code Online (Sandbox Code Playgroud)
我期待一些详细的输出,或者来自控制台的一些错误,但是在检查文件时nm
我只发现了1个差异
nm o* --demangle
onorm:
0000000000000000 T foo(float)
osan:
U __ubsan_handle_divrem_overflow
0000000000000000 T foo(float)
Run Code Online (Sandbox Code Playgroud)
所以在清理版本中有一个未定义的符号,其名称类似于我在编译时使用的清洁剂; 但是一切都是"沉默的",而且从铿锵的前端根本没有输出.
我应该如何使用消毒剂以及什么是正确的工作流程?那个未定义的符号有什么意义?
我打开了-fsanitize=undefined
使用Catch(单元测试库)的项目.来自Catch的一行被发信号通知此标志导致未定义的行为.我设法做了一个孤立的例子:
#include <iomanip>
#include <sstream>
int main()
{
std::ostringstream os;
os << "0x" << std::setfill('0') << std::hex;
}
Run Code Online (Sandbox Code Playgroud)
编译:
clang++ -fsanitize=undefined main.cpp
Run Code Online (Sandbox Code Playgroud)
如果我运行它,将给出以下打印:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/ios_base.h:96:24: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/ios_base.h:76:67: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
Run Code Online (Sandbox Code Playgroud)
这对我来说是clang 3.6.0
和一个有clang的朋友3.4-1ubuntu3
.在gcc版本上我不会发生这种情况4.9.2
那么这里有什么?这段代码真的很糟糕,还是clang的结尾有什么可疑的?
如何在QMake的.pro
文件中启用消毒剂的使用?
我找到了几个QMAKE_CXXFLAGS
自我修改的资源,但介绍性博客文章说:
它被安排在开发分支(Qt 5.2),因为它是一个新功能,但你应该很好地挑选它,例如Qt 5.0.然后,您可以使用-address-sanitizer配置Qt,并为您自己的应用程序运行qmake CONFIG + = address_sanitizer.
但是,添加CONFIG+=address_sanitizer
似乎没有效果.
我正在尝试将Google的Address Sanitizer与CUDA项目结合使用,更准确地说是使用OpenCV cuda功能.但是我在第一次cuda电话上遇到了"内存不足"的错误.
OpenCV Error: Gpu API call (out of memory) in getDevice, file opencv-2.4.11/src/opencv-2.4.11/modules/dynamicuda/include/opencv2/dynamicuda/dynamicuda.hpp, line 664
terminate called after throwing an instance of 'cv::Exception'
what(): opencv-2.4.11/src/opencv-2.4.11/modules/dynamicuda/include/opencv2/dynamicuda/dynamicuda.hpp:664: error: (-217) out of memory in function getDevice
Run Code Online (Sandbox Code Playgroud)
它可以复制
#include <opencv2/gpu/gpu.hpp>
int main()
{
cv::gpu::printCudaDeviceInfo(cv::gpu::getDevice());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用.编译
clang++ -fsanitize=address -lstdc++ -lopencv_gpu -lopencv_core -o sanitizer sanitizer.cpp && LD_LIBRARY_PATH=/usr/local/lib ./sanitizer
Run Code Online (Sandbox Code Playgroud)
我用gcc得到了同样的结果.我也尝试过将cuda函数列入黑名单而没有结果.
现在使用没有opencv的cuda:
#include <cuda_runtime.h>
int main()
{
int count = -1;
cudaGetDevice(&count);
cout << "Device count: " << count << endl; …
Run Code Online (Sandbox Code Playgroud) 几天后,我在Xcode 7.3中启动Address Sanitizer时出现以下问题.当Sanitizer发现问题(实际上被文件抑制)时,打印到Xcode控制台的错误消息:
== 13392 ==警告:无法在fd 55写入符号化程序
== 13392 ==警告:无法在fd 55写入符号化程序
== 13392 ==警告:无法在fd 55写入符号化程序
== 13392 ==警告:无法在fd 55写入符号化程序
== 13392 ==警告:无法使用并重启外部符号器!
我在存储库中找到了错误消息但仍然无法解释发生了什么.显然内部写入功能失败但我不知道是什么导致这种情况.有任何想法吗?