当试图调试由 seg-fault 抛出的核心时,它崩溃的行在我看来并没有真正的意义;有两个整数比较,结果存储在布尔值中。这是未简化的代码:
bool doLog = level >= debugLevel;
这是它崩溃的程序集代码:
cmp %ebx,0x14(%rbp)
// ebx = 3
// rbp = 0x6e696c7265
但是,当尝试打印存储在 rbp 中的地址值时,我收到一个 gdb 错误:"无法访问地址 0x6e696c7279 的内存">
让我烦恼的是,在打印debugLevel的地址时,我会得到一个不同的地址,然后存储在用于cmp的rbp寄存器中:
p &debugLevel => 0x6e696c7279
i r rbp => 0x6e696c7265
0x6e696c7265
看起来像字母的ASCII代码。 您可能用字符串字节覆盖了指针。
(例如,缓冲区溢出可能踩到了保存的 RBP 值,然后在恢复 RBP 后函数返回到其调用方,当调用方尝试使用 RBP 作为帧指针时中断对局部变量的访问。 实际上,RBP+14
不会是帧指针,除非这可能是在 Windows 上并且编译器在返回地址上方的阴影空间中分配了该本地指针。
打印调试级别的地址我会得到一个不同的地址,然后存储在用于 cmp 的 rbp 寄存器中的内容
GDB 从调试信息中知道&debugLevel
= RBP+0x14。
这就是为什么cmp
指令使用位移的寻址模式0x14
,特别是0x14(%rbp)
. 因此,从损坏的基址计算&debugLevel
会给你另一个错误的地址。
0x6e696c7279 - 0x6e696c7265 = 0x14 = 20
. 这部分不有趣或与您的内存损坏错误无关。