提问人:doliphin 提问时间:8/28/2023 更新时间:8/28/2023 访问量:87
为什么 -fsanitize=undefined 不接受(我认为是)UB?
Why doesn't -fsanitize=undefined pick up on (what I think is) UB?
问:
auto vec = std::vector<int>({1, 2, 3});
std::cout << *vec.end() << std::endl;
这里有一些我认为是UB的简单代码。但是,使用以下步骤进行编译:
g++ -std=c++23 -Wall -Wextra -g -fsanitize=undefined -o ./target/src/main.cpp.o src/main.cpp
g++ -fsanitize=undefined -o ./target/main ./target/src/main.cpp.o
产生一个非常愉快的消毒剂和输出!0
我认为连续集合迭代器在 C++ 中的工作方式是它们指向第一个越界内存位置。
{1, 2, 3} ?, ?, ?, ...
^ begin ^ end
我的想法是,创建任何任意指针在技术上都是安全的,但取消引用此指针是不安全的,因此这是创建迭代器的良好方法。当然,这不太可能是问题,所以让我知道我哪里出了问题!:)fsanitize
答:
2赞
Jan Schultke
8/28/2023
#1
你是对的;这是未定义的行为,一些消毒剂应该注意到它。Clang 的 UBSan 检测到它,而 GCC 的 ASan 可以:
#include <iostream>
#include <vector>
int main() {
auto vec = std::vector<int>({1, 2, 3});
std::cout << *vec.end() << std::endl;
}
这将产生以下错误:
==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x50200000001c at pc 0x00000040153e bp 0x7ffcd56c77c0 sp 0x7ffcd56c77b8
READ of size 4 at 0x50200000001c thread T0
#0 0x40153d in main /app/example.cpp:6
#1 0x7faa3ef48082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
#2 0x40120d in _start (/app/output.s+0x40120d) (BuildId: b859bb13bb93e5af8f52cb0ac4198ad4bf2002c3)
通常,通常应该使用来捕获更广泛的错误。或者,使用外部工具,如 valgrind。-fsanitize=address,undefined
评论
2赞
NathanOliver
8/28/2023
如果你让这个例子不那么简单,它仍然无法检测到:godbolt.org/z/TaGKcdM9W
0赞
Jan Schultke
8/28/2023
@NathanOliver我认为这可能超出了消毒程序的能力,只能通过额外的运行时断言来获取。当您添加 之后 ,它会再次拾取它。vec.shrink_to_fit()
vec.clear()
1赞
user17732522
8/29/2023
要捕获 libstdc++ 中未定义库的行为,而这些行为恰好不是具体实现的核心语言未定义行为,可以使用 和 。-D_GLIBCXX_ASSERTIONS
-D_GLIBCXX_DEBUG
评论
-fsanitize=address,undefined
-fsanitize=address
: godbolt.org/z/85zvTneYP