AddressSanitizer 随机抛出 SIGSEGV,没有任何解释

问题描述 投票:0回答:1

项目

我目前正在开发一个 C++ 游戏项目。 我用

-g3 -std=c++2a -Wall ... -fsanitize=address -fsanitize=leak
编译每个源文件来检查泄漏和段错误

主要问题

问题是,asan(地址或泄漏)随机(五分之一)在没有任何诊断的情况下使用 SIGSEGV 到达主程序之前终止程序。

AddressSanitizer:DEADLYSIGNAL
=================================================================
==28573==ERROR: AddressSanitizer: SEGV on unknown address 0x625505a4ce68 (pc 0x7cc52585f38f bp 0x000000000000 sp 0x7fff63949020 T0)
==28573==The signal is caused by a READ memory access.
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.

SEGV 发生的地址总是不同的,PC 也是如此(最后 3 位数字除外,分别是 e68、38f)

它运行的系统

我的机器是

Arch Linux 6.7.0-arch3-1
,我正在使用
g++ (GCC) 13.2.1 20230801
GNU gdb (GDB) 13.2
,这是撰写本文时存储库上的最新版本

我尝试过的事情

我不知道如何找出这个错误,也不知道是什么原因导致的。

代码中

我确信问题发生在 main 之前,因为打印某些内容(使用 cout 或 printf)没有效果,使用信号处理程序也是如此,

signal(SIGSEGV, &handle);

asan 是其中的一部分

没有asan,SEGV 就不会发生。 (我已经尝试了50~次,每次程序都正确启动)

gdb

在使用 asan 编译的程序和关闭 ASLR 的情况下使用 gdb 会导致 SIGSEGV 和自动捕获

问题的组装说明

考虑到问题发生的奇怪地址模式,我尝试在任何以 38f (

$pc
) 结尾的
watch ((size_t)$pc & 0xfff) == 0x38f
上使用观察点。 观察点有效,有问题的地址包含在 libc 函数(
do_lookup_x
或类似函数)中,在主程序开始之前,该函数似乎被调用了数千次,这使得这种方式的调试实际上是一场噩梦。

问题

我想问是否有人知道如何从asan、gdb或任何其他工具获取更多信息,因为目前我没有足够的信息来知道问题发生在哪里,或者即使问题是在不管是不是我的。


更新

@marekR 和 @eljay 建议与某些 glibc 函数/名称发生某种符号冲突。我的大多数定义都包含在命名空间中(因此名称也被破坏),唯一足以与其他名称冲突的通用函数是

init()
loop()
terminate()
。更改名字并没有解决问题

按照 @ÖöTiib 建议,我用

git bisect
测试了我的 git 历史记录,这个问题自 2019 年第一次提交以来就出现了,这意味着它可能一直没有被注意到,(我是唯一在这方面工作的人)项目但似乎不太可能),这是我的机器本地因素的组合,或者其他因素

@EmployedRussian 建议将 ASLR 与 gdb 一起使用。在 gdb 下使用

-fsantize=address
并使用
set disable-randomization off
捕获 SIGSEGV。
抛出信号处的堆栈跟踪。

Program received signal SIGSEGV, Segmentation fault.
do_lookup_x (undef_name=undef_name@entry=0x74267e33e6d8 "_thread_db_sizeof_pthread", new_hash=new_hash@entry=3872132951, old_hash=old_hash@entry=0x7ffd8dd33cf8, ref=0x0, result=result@entry=0x7ffd8dd33d00, scope=<optimized out>, i=0, version=0x0, flags=3,
    skip=<optimized out>, type_class=0, undef_map=<optimized out>) at dl-lookup.c:405
405       const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
(gdb) where
#0  do_lookup_x (undef_name=undef_name@entry=0x74267e33e6d8 "_thread_db_sizeof_pthread", new_hash=new_hash@entry=3872132951, old_hash=old_hash@entry=0x7ffd8dd33cf8, ref=0x0, result=result@entry=0x7ffd8dd33d00, scope=<optimized out>, i=0, version=0x0, flags=3,
    skip=<optimized out>, type_class=0, undef_map=<optimized out>) at dl-lookup.c:405
#1  0x000074267e9030b8 in _dl_lookup_symbol_x (undef_name=0x74267e33e6d8 "_thread_db_sizeof_pthread", undef_map=<optimized out>, ref=0x7ffd8dd33d88, symbol_scope=<optimized out>, version=0x0, type_class=0, flags=3, skip_map=0x0) at dl-lookup.c:793
#2  0x000074267d97300e in do_sym (handle=<optimized out>, name=0x74267e33e6d8 "_thread_db_sizeof_pthread", who=0x74267e2fffb3 <__sanitizer::ThreadDescriptorSize()+35>, vers=vers@entry=0x0, flags=flags@entry=2) at dl-sym.c:146
#3  0x000074267d973331 in _dl_sym (handle=<optimized out>, name=<optimized out>, who=<optimized out>) at dl-sym.c:195
#4  0x000074267d8a6ae8 in dlsym_doit (a=a@entry=0x7ffd8dd33ff0) at dlsym.c:40
#5  0x000074267e8fa4e1 in __GI__dl_catch_exception (exception=exception@entry=0x7ffd8dd33f50, operate=0x74267d8a6ad0 <dlsym_doit>, args=0x7ffd8dd33ff0) at dl-catch.c:237
#6  0x000074267e8fa603 in _dl_catch_error (objname=0x7ffd8dd33fa8, errstring=0x7ffd8dd33fb0, mallocedp=0x7ffd8dd33fa7, operate=<optimized out>, args=<optimized out>) at dl-catch.c:256
#7  0x000074267d8a64f7 in _dlerror_run (operate=operate@entry=0x74267d8a6ad0 <dlsym_doit>, args=args@entry=0x7ffd8dd33ff0) at dlerror.c:138
#8  0x000074267d8a6b75 in dlsym_implementation (dl_caller=<optimized out>, name=<optimized out>, handle=<optimized out>) at dlsym.c:54
#9  ___dlsym (handle=<optimized out>, name=<optimized out>) at dlsym.c:68
#10 0x000074267e2fffb3 in __sanitizer::ThreadDescriptorSize () at /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp:298
#11 0x000074267e3017ae in __sanitizer::ThreadDescriptorSize () at /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp:294
#12 __sanitizer::GetTls (size=0x7ffd8dd340c8, addr=0x74267e8d2040) at /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp:498
#13 __sanitizer::GetThreadStackAndTls (main=true, stk_addr=stk_addr@entry=0x74267e8d2020, stk_size=stk_size@entry=0x7ffd8dd340d0, tls_addr=tls_addr@entry=0x74267e8d2040, tls_size=tls_size@entry=0x7ffd8dd340c8)
    at /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp:595
#14 0x000074267e2f0ff4 in __asan::AsanThread::SetThreadStackAndTls (this=this@entry=0x74267e8d2000, options=<optimized out>) at /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_thread.h:77
#15 0x000074267e2f14ee in __asan::AsanThread::Init (this=this@entry=0x74267e8d2000, options=options@entry=0x0) at /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_thread.cpp:234
#16 0x000074267e2f19e5 in __asan::AsanThread::ThreadStart (this=this@entry=0x74267e8d2000, os_id=62202) at /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_thread.cpp:264
#17 0x000074267e2f2604 in __asan::CreateMainThread () at /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_thread.cpp:295
#18 0x000074267e2ee9df in __asan::AsanInitInternal () at /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_rtl.cpp:480
#19 0x000074267e8fe02a in _dl_init (main_map=0x74267e92d2d0, argc=1, argv=0x7ffd8dd341d8, env=0x7ffd8dd341e8) at dl-init.c:122
#20 0x000074267e9142d0 in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#21 0x0000000000000001 in ?? ()
#22 0x00007ffd8dd3473a in ?? ()
#23 0x0000000000000000 in ?? ()
Program received signal SIGSEGV, Segmentation fault.
do_lookup_x (undef_name=undef_name@entry=0x74267e33e6d8 "_thread_db_sizeof_pthread", new_hash=new_hash@entry=3872132951, old_hash=old_hash@entry=0x7ffd8dd33cf8, ref=0x0, result=result@entry=0x7ffd8dd33d00, scope=<optimized out>, i=0, version=0x0, flags=3,
    skip=<optimized out>, type_class=0, undef_map=<optimized out>) at dl-lookup.c:405
405       const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);

从这段代码来看,错误是运行时读取符号表导致的。我不确定为什么这段代码在这里或者为什么它有时会失败。

c++ linux segmentation-fault gdb address-sanitizer
1个回答
0
投票

我遇到了同样的问题;只需降级内核即可。 我不知道为什么,但似乎 asan 与当前版本不兼容。运行以下命令并快速重新启动后,一切恢复正常:

pacman -Udd file:///var/cache/pacman/pkg/linux-headers-6.6.10.arch1-1-x86_64.pkg.tar.zst file:///var/cache/pacman/pkg/linux-6.6.10.arch1-1-x86_64.pkg.tar.zst
将两个文件中的“6.6.10.arch1-1”替换为您想要降级到的版本,它应该可以解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.