项目
我有一个C++游戏项目,目前正在开发中.
我用-g3 -std=c++2a -Wall ... -fsanitize=address -fsanitize=leak
编译每个源文件,以判断泄漏和段错误
主要问题是
问题是,随机(每5次中有1次)ASAN(地址或泄漏)在到达Main之前终止程序,并带有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) 13.2
,这是我写这篇文章时最新的存储库
我try 过的东西
我不知道如何追查这个漏洞,也不知道是什么原因导致了它.
在代码中
我确信问题发生在main之前,因为打印一些东西(使用cout或print tf)没有任何效果,使用信号处理程序也是如此,signal(SIGSEGV, &handle);
阿山是其中的一部分
没有ASAN,SEGV就不会发生.(我已经try 了50~次,程序每次都正确启动)
地理数据库
在asan和ASLR关闭的情况下使用地理数据库编译程序会导致SIGSEGV和自动捕获
问题的汇编说明
考虑到出现问题的地址的奇怪模式,我try 在以38f(watch ((size_t)$pc & 0xfff) == 0x38f
)结尾的任何$pc
上使用观察点.
观察点工作,有问题的地址包含在libc函数(do_lookup_x
或类似函数)中,在Main开始之前,该函数似乎被调用了数千次,使得这种调试实际上是一场噩梦.
问题是
我想问一下,是否有人知道如何从ASAN、GDB或任何其他工具中获取更多信息,因为目前我没有足够的信息来知道问题发生在哪里,甚至问题是否出在我身上.
更新
@marekR和@eljay建议使用一些glibc函数/名称进行某种符号冲突.我的大多数定义都包含在一个名称空间中(因此也称为Mangleed),唯一通用到足以与其他名称冲突的函数是init()
、loop()
和terminate()
.更改他们的名字并没有解决这个问题
根据@Öötiib的建议,我用git bisect
测试了我的GIT历史,这个问题自2019年第一次提交以来就出现了,这意味着它可能一直没有被注意到(我是唯一一个在这个项目上工作的人,但似乎不太可能),这是我的机器本地的因素或其他因素的组合