最新版本的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似乎有效,但这个名字看起来很内部.
考虑以下代码:
#include <string_view>
constexpr std::string_view f() { return "hello"; }
static constexpr std::string_view g() {
auto x = f();
return x.substr(1, 3);
}
int foo() { return g().length(); }
Run Code Online (Sandbox Code Playgroud)
如果我用 GCC 10.2 和 flags 编译它--std=c++17 -O1,我会得到:
foo():
mov eax, 3
ret
Run Code Online (Sandbox Code Playgroud)
此外,据我所知,这段代码没有任何未定义的行为问题。
但是 - 如果我添加 flag -fsanitize=undefined,编译结果是:
.LC0:
.string "hello"
foo():
sub rsp, 104
mov QWORD PTR [rsp+80], 5
mov QWORD PTR [rsp+16], 5
mov QWORD PTR [rsp+24], OFFSET FLAT:.LC0
mov QWORD PTR [rsp+8], 3
mov QWORD …Run Code Online (Sandbox Code Playgroud) clang++和消毒剂都会g++针对这个简单代码的数据竞争产生类似的警告。难道是虚惊一场?问题是什么?
代码:
#include <thread>
struct A
{
void operator()()
{
}
};
struct B
{
void operator()()
{
}
};
int main(void)
{
// callable objects are created and moved into thread
std::thread t1(A{});
std::thread t2(B{});
t1.join();
t2.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译标志:
-pthread -O0 -g -fsanitize=thread -fsanitize=undefined
Run Code Online (Sandbox Code Playgroud)
消毒剂输出g++:
==================
WARNING: ThreadSanitizer: data race (pid=80173)
Write of size 8 at 0x7b0400000800 by thread T2:
#0 pipe ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1726 (libtsan.so.0+0x3ea28)
#1 __sanitizer::IsAccessibleMemoryRange(unsigned long, unsigned long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:276 (libubsan.so.1+0x20102)
#2 …Run Code Online (Sandbox Code Playgroud) 今天我读了一篇关于GCC Undefined Behavior Sanitizer(ubsan)的文章.但是,当我按照那里的步骤(添加-fsanitize=undefined到我的代码中)时,编译器(UCCntu 15.04上的GCC 4.9.2)说某些引用没有定义:
||=== Build: Debug in Entangle (compiler: GNU GCC Compiler) ===|
obj/Debug/EntangleApp.o||In function `EntangleApp::OnInit()':|
/home/ilya/Projects/Entangle/EntangleApp.cpp|31|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|31|undefined reference to `__ubsan_handle_load_invalid_value'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|32|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|34|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|34|undefined reference to `__ubsan_handle_load_invalid_value'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|34|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|34|undefined reference to `__ubsan_handle_load_invalid_value'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|35|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|37|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|37|undefined reference to `__ubsan_handle_load_invalid_value'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|43|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|43|undefined reference to `__ubsan_handle_load_invalid_value'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|52|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Projects/Entangle/EntangleApp.cpp|52|undefined reference to …Run Code Online (Sandbox Code Playgroud) 今天我花了几个小时试图理解为什么这段代码会出现错误,g++6.2并且尽快g++7.0按照预期clang++3.9 (和4.0)工作.
我将问题简化为85行自包含代码片段,在正常执行时不会出现段错误,但始终在UBSAN下报告错误.
该问题在wandbox上可以重现,通过编译g++7,启用优化并-fsanitize=undefined作为额外标志传递.
这是UBSAN报道的内容:
prog.cc: In function 'int main()':
prog.cc:61:49: warning: 'ns#0' is used uninitialized in this function [-Wuninitialized]
([&] { ([&] { n.execute(ns...); })(); })();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
prog.cc:28:10: note: 'ns#0' was declared here
auto execute(TNode& n, TNodes&... ns)
^~~~~~~
prog.cc:30:9: runtime error: member call on null pointer of type 'struct node_then'
Run Code Online (Sandbox Code Playgroud)
g++ …
我试图通过函数指针表调用一些C++函数,该表从共享对象导出为C符号.该代码实际上正在工作,但Clang的未定义行为清理程序(= UBSan)看到我所做的调用是非法的,如下所示:
==11410==WARNING: Trying to symbolize code, but external symbolizer is not initialized!
path/to/HelloWorld.cpp:25:13: runtime error: call to function (unknown) through pointer to incorrect function type 'foo::CBar &(*)()'
(./libFoo.so+0x20af0): note: (unknown) defined here
Run Code Online (Sandbox Code Playgroud)
由于Clang的未定义行为清理程序,间接调用函数通过函数指针返回C++标准类对象的引用是合法的,但对于用户定义的类是非法的.有人可以告诉我它有什么问题吗?
我一直在尝试使用Clang-llvm 3.4-1ubuntu3和CMake 2.8.12.2在Ubuntu 14.04上构建项目.要重现此现象,请将以下5个文件放在同一目录中并调用build.sh.它将创建一个makefile并构建项目,并运行可执行文件.
foo.h中
#ifndef FOO_H
#define FOO_H
#include <string>
//
#define EXPORT __attribute__ ((visibility ("default")))
namespace foo {
class CBar
{
// empty
};
class CFoo
{
public:
static CBar& GetUdClass();
static std::string& GetStdString();
}; …Run Code Online (Sandbox Code Playgroud) 我这里有一个小型单元测试,其行为未定义。
源代码:
#include <gtest/gtest.h>
TEST(test, test)
{
int k = 0x7fffffff;
k += 1; // cause integer overflow
}
GTEST_API_ int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Run Code Online (Sandbox Code Playgroud)
我在 CMakeLists.txt 中启用 UBSAN:
cmake_minimum_required (VERSION 3.12)
project(ub CXX)
find_package(GTest REQUIRED)
add_executable (ub_test ub_test.cpp)
target_link_libraries (ub_test GTest::GTest)
target_compile_options(ub_test PRIVATE -fsanitize=undefined)
target_link_options (ub_test PRIVATE -fsanitize=undefined)
Run Code Online (Sandbox Code Playgroud)
UBSAN 正确识别未定义的行为:
Run Code Online (Sandbox Code Playgroud)/home/steve/src/ub/ub_test.cpp:6:7: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
然而,我的测试仍然通过了。
Run Code Online (Sandbox Code Playgroud)[==========] Running 1 test from 1 test …
Clang 8发行说明中有以下内容:
- 允许在MinGW上使用Address Sanitizer和Undefined Behavior Sanitizer。
但是,我无法弄清楚如何正确使用它们。
我将Clang 8.0.0与MSYS2 MinGW GCC结合使用。确切的细节在问题的底部。
我正在尝试编译以下最少的代码:
1.cpp
#include <iostream>
int main()
{
// Testing ubsan
int x = 0x7fffffff;
x++;
std::cout << x << std::endl;
// Testing asan
int *y = new int;
delete y;
std::cout << *y << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
以下是结果-fsanitize=address:
# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No …Run Code Online (Sandbox Code Playgroud) 我在 Debian 8 x86_64 上使用 g++ 4.9.2。我发现未定义行为消毒剂 (UBsan) ( -fsanitize=undefined) 错误:
algebra.cpp:206:8: runtime error: load of value 127,
which is not a valid value for type 'bool'
Run Code Online (Sandbox Code Playgroud)
代码来自 Crypto++ 库。这是代码algebra.cpp:206(和一些相关代码):
206 struct WindowSlider
207 {
208 WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
209 : m_exp(expIn), m_windowModulus(Integer::One()), m_windowSize(windowSizeIn), m_windowBegin(0), m_fastNegate(fastNegate), m_firstTime(true), m_finished(false)
210 {
...
249 Integer m_exp, m_windowModulus;
250 unsigned int m_windowSize, m_windowBegin;
251 word32 m_expWindow;
252 bool m_fastNegate, m_negateNext, m_firstTime, m_finished;
253 };
Run Code Online (Sandbox Code Playgroud)
它在几个地方被调用,例如: …
为了更好地防止 UB 情况,例如:
#include <stdio.h>
int f(){
int x;
return x;
}
int main()
{
f();
while(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我今天更新了我的 GCC,所以我可以使用ubsan。我当前的版本是 5.3.0 根据gcc --version. 我以为这次更新会添加ubsan,但似乎不是因为在编译后C:\Users\my_name\Desktop>gcc -fsanitize=undefined a.c我得到了:
c:/mingw/bin/../lib/gcc/mingw32/5.3.0/../../../../mingw32/bin/ld.exe: 无法 fin d -lubsan
现在,我已经看到了这篇文章,但操作系统是Ubuntu 15.04我使用的,Win 8.1所以对我没有帮助。这里的评论之一说:
您将需要安装 libubsan 软件包。
但我不知道它是否是针对 的windows/ubuntu,即使是针对windows用户的,我也不知道该怎么做。
编辑:我也试过编译gcc -fno-sanitize=all a.c(有很多的选择在这里),这编译没有警告,所以我想GCC认识消毒剂以某种方式(因为它编译OK),但拒绝我原来编译尝试由于某种原因