nm 输出和 gdb 中的函数地址不同

Function address is different in nm output and gdb

我们只关注 Rect_IsEmpty() 功能。

nm 命令给我这个输出:

(...)    
00021af0 T Rect_IsEmpty
(...)

另一方面,当我启动 gdb 并看到这个函数的地址时,我得到:

(gdb) info address Rect_IsEmpty
Symbol "Rect_IsEmpty" is at 0x8057c84 in a file compiled without debugging.

谁能解释一下为什么这些地址不一样? gdb 从哪里得到这个地址?

nm 给你错位的名称符号 table 的地址偏移量,而 gdb 给你实际的虚拟进程的内存地址,每次你 运行 进程都会改变.

nm 只是一个工具,它显示您从代码段的开头偏移。你的情况:

00021af0 T Rect_IsEmpty

简单的意思是,在整个代码段中,在所有其他函数中,Rect_IsEmpty一个从代码段偏移00021af0,所以如果代码段的基址被重新定位到00000000,则偏移量将与地址相同,00021af0

在 运行 在 Linux 上执行 table 之前,ASLR 机制用于随机化地址,但不是全部,只是段的开始。因此,在 运行 执行 table 之前,您不能总是知道或依赖动态符号的地址,您只能从段起始地址开始偏移。

使用调试器查找函数地址时,您会在 ASLR 完成其工作后看到进程代码段内的符号地址。

Here is a good article from IBM about shared libraries and another one 关于过程链接 Table 和全局偏移 Table。

可执行文件将从不同的内存位置开始,使得其中的任何分配都不同。因此,任何函数都将具有与其之前执行时不同的内存地址。

关于你的问题,GDB 从调试信息中获取地址 - 它会显示绝对内存地址。