地址消毒器:"SEGV on unknown adress" 使用 throw-catch 和 printf 时

Address Sanitizer: "SEGV on unknown adress" when using throw-catch and printf

当我扔东西时,例如一个 int 或一个 char const*,并使用 printf 来检查错误,我得到一个 Address Sanitizer Error。

我在网上找不到任何类似的东西,而且我的代码示例非常基础,我真的不明白它怎么可能会产生错误。

减少代码示例:

#include <stdio.h>

int main() 
{
    try {
        throw 42;
    } catch (int msg) {
        printf("%d\n", msg);
    }
    return 0;
}

运行 代码时的控制台输出:

ASAN:SIGSEGV
=================================================================
==16533==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f3eb9c1a76c bp 0x7ffde2b6fde0 sp 0x7ffde2b6fdd0 T0)
#0 0x7f3eb9c1a76b (/home/[...]/build/test/sample+0xc476b)
#1 0x7f3eb7e38b44 (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
#2 0x7f3eb9c1a5d9 (/home/[...]/build/test/sample+0xc45d9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
==16533==ABORTING

禁用 -fsanitize 标志时,Valgrind 会给出以下提示:

==18103== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==18103== Command: ./build/test/sample
==18103== 
==18103== Invalid read of size 4
==18103==    at 0x109205: main (sample.cpp:11)
==18103==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==18103== 
==18103== 
==18103== Process terminating with default action of signal 11 (SIGSEGV)
==18103==  Access not within mapped region at address 0x0
==18103==    at 0x109205: main (sample.cpp:11)
==18103==  If you believe this happened as a result of a stack
==18103==  overflow in your program's main thread (unlikely but
==18103==  possible), you can try to increase the size of the
==18103==  main thread stack using the --main-stacksize= flag.
==18103==  The main thread stack size used in this run was 8388608.
==18103== 
==18103== HEAP SUMMARY:
==18103==     in use at exit: 148 bytes in 2 blocks
==18103==   total heap usage: 2 allocs, 0 frees, 148 bytes allocated
==18103== 
==18103== LEAK SUMMARY:
==18103==    definitely lost: 0 bytes in 0 blocks
==18103==    indirectly lost: 0 bytes in 0 blocks
==18103==      possibly lost: 132 bytes in 1 blocks
==18103==    still reachable: 16 bytes in 1 blocks
==18103==         suppressed: 0 bytes in 0 blocks
==18103== Rerun with --leak-check=full to see details of leaked memory
==18103== 
==18103== For counts of detected and suppressed errors, rerun with: -v
==18103== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 1 from 1)

编译器设置:在 Debian Jessie 上使用带有以下标志的 clang 3.5.0-10(摘自 Makefile):

CXX:=clang++

## generic warning-related stuff
WARNFLAGS:=-Wall -Wextra -Wextra-semi -pedantic
WARNFLAGS+= -Wsign-conversion -Wshorten-64-to-32
WARNFLAGS+= -Werror
## generic debugging-related stuff
DEBUGFLAGS:=-O2 -g3 -ggdb -fno-omit-frame-pointer
## harden program by performing additional checks
SANITIZER:=-fsanitize=address,signed-integer-overflow,shift,bool,bounds,vptr,integer-divide-by-zero,float-cast-overflow,float-divide-by-zero,enum
HARDENCXXFLAGS:=-ftrapv -D_FORTIFY_SOURCE=2 -DDEBUG=1 -UNDEBUG -fstack-protector-all -fPIE -Wformat -Wformat-security -Wformat-nonliteral $(SANITIZER)
## C++ compiler flags
DEF += -D_XOPEN_SOURCE_EXTENDED
CXXFLAGS:=$(WARNFLAGS) -stdlib=libc++ -std=c++14 -maes $(DEBUGFLAGS) $(HARDENCXXFLAGS) $(INCLUDEFLAGS) $(DEF) -Xclang -fcolor-diagnostics

有什么想法吗?

原来只有在链接到包含 std::cerr << "Error message" << std::endl; 等行的文件后才会出现问题 - 删除这些行会使地址消毒器错误消失。

深入挖掘,使用具有特定编译标志组合的虚函数 and/or 似乎是一个问题。

要查看孤立的问题,请参阅 AddressSanitizer / LeakSanitizer Error with -lsupc++ and -stdlib=libc++ on a never called virtual function that writes to a stream