地址Sanitizer:" SEGV在未知的地址"当使用throw-catch和printf时

时间:2015-11-19 23:34:51

标签: c++ clang clang++ address-sanitizer

当我扔东西时,例如一个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

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

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

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

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