码迷,mamicode.com
首页 > 编程语言 > 详细

c/c++ 符号表以及static\const修饰变量

时间:2018-03-30 01:13:00      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:内容   大小   访问   ati   oid   oda   字段表   执行   inf   

 1 符号表

 

2 代码

每个变量都标了号,防止看混了.

int _1_cpp_i_ = 1;
const int _2_cpp_c_i_ = 1;
static int _2_cpp_s_i_ = 1;

void _4_cpp_v_func_i_i_(int, int)
{
    return;
}

int _5_cpp_i_func_i_i_(int, int)
{
    return 1;
}

extern "C" {
int _6_c_i_ = 1;
const int _7_c_c_i_ = 1;
static int _8_c_s_i_ = 1;

void _9_c_v_func_i_i_(int, int)
{
    return;
}

int _0_c_i_func_i_i_(int, int)
{
    return 1;
}
}

 

然后编译并查看,注意这里使用 g++

技术分享图片

 

然后看一下,下表4代表的段,是那个段:

技术分享图片

随便百度一下:rodata的意义同样明显,ro代表read only,即只读数据(const)。

额外补一些:

  1. 常量不一定就放在rodata里,有的立即数直接编码在指令里,存放在代码段(.text)中。
  2. 对于字符串常量,编译器会自动去掉重复的字符串,保证一个字符串在一个可执行文件(EXE/SO)中只存在一份拷贝。
  3. rodata是在多个进程间是共享的,这可以提高空间利用率。

但是这只是编译器说这段不能修改,其实真正强制这个段的内容不能更改的是操作系统在分配页的时候,给页加上的属性.

 

如果使用gcc编译:

技术分享图片

 

使用gcc 和使用g++ 编译结果居然一样,可见,gcc 编译 的时候也使用了和g++一样的标识符修饰规则.

而extern "C" 的作用,现在变成了,按照以前 gcc 的形式修饰标识符(因为现在gcc 标识符修改规则已经变了)

 

3 综上

static 和 const修饰的全局变量,默认只在本文件中可见.(注意通常是 cc文件,因为.h文件被 include进去了,不存在可不可见了)

 

4 从elf 符号表角度分析

符号表中的每一项表示一个符号的信息.记录在结构体中

struct Elf32_Sym
{
  Elf32_Word    st_name;   /* 符号名,是在字符串表中的下表 */
  Elf32_Addr    st_value;  /* 符号对应的只,可能是个地址,具体跟富豪有关*/
  Elf32_Word    st_size;   /* 符号大小 */
  unsigned char st_info;   /* 符号绑定信息 */
  unsigned char st_other;  /* 其他,目前为0,没有使用 */
  Elf32_Section st_shndx;  /* 符号所在的段 */
};

readelf -s 只是将信息汇总展示而已.

其中于本文有关的就是 st_info 和st_shndx.

前者指明了该标志服是否在文件外可见,后者指明了标识符所在的段,间接指明是否可以修改.

 

注意,符号表是编译器和连接器之间的约定.连接器在连接符号的时候,如果遇到符号的 st_info 字段表明尽在文件内可见,那么连接器报错,标识找不到标识符(但其实他找到了.恩,真的找到了.)

 

 

5 补充

const定义的全局变量不能被其他文件访问,必须加extern 才能被连接.(注意是 cc 文件中,不能在 .h 文件.上面说了 .h 文件会被展开)

c/c++ 符号表以及static\const修饰变量

标签:内容   大小   访问   ati   oid   oda   字段表   执行   inf   

原文地址:https://www.cnblogs.com/perfy576/p/8673394.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!