有些人可以帮助我理解这一点: -
以下是gdb的摘录。我的程序崩溃后,我在gdb中打开了二进制和核心文件并发出了命令info frame
:
(gdb) info frame
Stack level 0, frame at 0xb75f7390:
eip = 0x804877f in base::func() (testing.cpp:16); saved eip 0x804869a
called by frame at 0xb75f73b0
source language c++.
Arglist at 0xb75f7388, args: this=0x0
Locals at 0xb75f7388, Previous frame's sp is 0xb75f7390
Saved registers:
ebp at 0xb75f7388, eip at 0xb75f738c
“ebp”,“eip”,“Locals at”和“Previous Frame's sp”是什么意思?请解释
答案 0 :(得分:5)
维基百科文章Call stack中的这个图表可能有所帮助:
GDB的info frame
对应于运行时程序中调用的函数。从输出中,我们可以推断出有关堆栈帧布局的信息:
base::func()
call
指令推送this
参数存储到base::func()
, 0x00000000 。我将逐行解释info frame
输出:
Stack level 0, frame at 0xb75f7390:
堆栈级别0表示这是最新帧。 frame at
之后的地址称为规范帧地址(CFA)。在x86上,这被定义为在执行调用指令之前的前一帧的堆栈指针( ESP )的值。
eip = 0x804877f in base::func() (testing.cpp:16); saved eip 0x804869a
EIP 是x86指令指针。 saved eip
是返回地址。
如果您尝试使用info symbol 0x804869a
查找包含 0x804869a 的函数,则应该指向调用base::func()
的函数内部。
called by frame at 0xb75f73b0
called by
显示前一帧的规范帧地址。我们可以看到堆栈指针在两帧之间前进了32个字节(0xb75f73b0 - 0xb75f7390 = 32)。
source language c++.
Arglist at 0xb75f7388, args: this=0x0
Locals at 0xb75f7388, Previous frame's sp is 0xb75f7390
x86 ABI在堆栈上传递参数。 base::func()
只有一个隐式this
参数。事实是0x0
即NULL
预示着不适。在旁注中,Arglist
和Locals
似乎在x86和x86-64上的info frame
中始终具有相同的值。
Saved registers:
ebp at 0xb75f7388, eip at 0xb75f738c
Saved registers
反映了在函数入口处保存的寄存器。它列出了旧寄存器值在堆栈中保存的位置。已保存的 EIP 是返回地址,因此,如果您使用x/a 0xb75f738c
检查存储在 0xb75f738c 的地址,则应该提供 0x804869a 。此处列出 EBP 的事实意味着您的代码可能未使用-fomit-frame-pointer
编译并具有标准函数序言:
push %ebp
movl %esp, %ebp
在base::func()
的乞讨时,设置 EBP 作为帧指针。
答案 1 :(得分:0)
要分析核心文件,请执行:
$ gdb可执行核心
gdb $ bt - backtrace
或gdb $ fr 0 - 运行时堆栈中最上面的帧 gdb $ fr 1&这样就会给你函数调用的顺序,这导致了Seg Fault。
这里,gdb $ info框架为您提供有关第0帧的信息。