设为首页
收藏本站
切换到窄版
登录
立即注册
找回密码
搜索
搜索
本版
帖子
用户
快捷导航
论坛
BBS
C语言
C++
NET
JAVA
PHP
易语言
数据库
IE盒子
»
论坛
›
IE盒子
›
C++
›
C/C++ 符号表
返回列表
发帖
查看:
114
|
回复:
0
C/C++ 符号表
[复制链接]
刀疤
刀疤
当前离线
积分
13
4
主题
5
帖子
13
积分
新手上路
新手上路, 积分 13, 距离下一级还需 37 积分
新手上路, 积分 13, 距离下一级还需 37 积分
积分
13
发消息
发表于 2023-3-25 18:26:35
|
显示全部楼层
|
阅读模式
概念
Symbol :
函数&变量的名称
。
Symbol Table:
Symbol的列表
。
符号表是程序/单元中“符号”的列表。符号通常是变量或函数的名称。
符号表可用于确定变量或函数在内存中的位置
。 简而言之,Symbol Table 是分配给函数&变量的名称与其
在内存中的地址的映射
,包括类型、范围和大小等元数据。
最终由编译器使用。
通常,C 或 C++ 编译器将单个源文件编译为扩展名为 .obj 或 .o 的目标文件。目标文件包含可执行代码和数据的集合,
链接器
可以将其处理成工作应用程序或共享库。
目标文件中有一个称为
符号表的数据结构
,
它将目标文件中的不同项目映射到链接器可以理解的名称
。如果您从代码中调用函数,编译器不会将例程的最终地址放入目标文件中。相反,它将一个占位符值放入代码中并添加一个注释,告诉链接器从它正在处理的所有目标文件中
查找各种符号表中的引用
,并将最终位置粘贴在那里。
其次,还有.so 或 .dll 中的符号表。这是由链接器生成的,用于命名库用户可见的所有函数和数据项。这允许系统进行运行时链接,将对这些名称的开放引用解析为库在内存中加载的位置。
nm 目标文件: 列出目标文件的符号表。
例子
我们可以通过下边的一个简单的例子来理解这些基础概念。
1、生成源文件main.c
/**
*函数funcA
*/
int funcA() {
return 0;
}
int main(int argc, char *argv[]){
return 0;
}2、 在当前目录下生成汇编文件 gcc -S main.c 可以直接打开生成的汇编文件:main.s
3、在当前目录下生成目标文件 gcc -c main.c
生成的main.o不能直接以文本的格式打开。
查看main.o的信息: objdump -h main.o 信息如下: 函数名位于.text中。
使用 nm命令查看符号信息: nm main.o
可以看到两个函数名: funcA & main
4、 全局变量&静态变量
接下来我们在main.c里添加一个 全局变量 & 一个静态变量,再执行 1、2、3步骤看一下执行结果。
/**
*全局变量
*/
int globalA = 2022;
/**
*静态变量
*/
static int globalB = 2023;
int funcA() {
return 0;
}
int main(int argc, char *argv[]){
return 0;
}此时查看汇编文件 main.s 结果如下:
main.s
objdump -h main.o 查看目标文件结果如下:
main.o
nm main.o结果如下:
5、局部变量
自此我们可以看到 函数&全局变量&静态变量都会在生成目标文件的时候有自己的符号名称,局部变量呢?
那我们可以在函数funcA & main函数里添加两个局部变量,main代码改进为下边这样:
int globalA = 2022;
static int globalB = 2023;
int funcA() {
int localFuncAValue = 13;
return 0;
}
int main(int argc, char *argv[]){
int localMainValue = 14;
return 0;
}
查看main.s文件结果如下:
此时我们发现局部变量并没有生成符号
。
movl $14, -4(%rbp) : rbp 堆栈基指针
结论
1、函数&全局变量&静态变量会生成符号。
2、局部变量不会生成符号,最终是分配在栈内存中,不会在函数外部被引用。
参考:
GCC编译流程(一)
Linux 命令(63)-- nm 命令
回复
使用道具
举报
返回列表
发帖
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
浏览过的版块
数据库
快速回复
返回顶部
返回列表