共享对象(库)数据段地址无关性
在看《程序员的自我修养——链接、装载与库》,发现相见恨晚。一口气看了不少。
在7.3.5节开头是这样的:
大牛能解释一下,为何变量a是地址无关的(地址随着装载而改变),而变量p是绝对地址?
在链接的时候, 虽然不存在真实的内存, 但是链接器会产生一个虚拟内存布局. 这个布局表明了如果这个动态库按设定的基地址加载, 哪个变量就会在哪个位置. 链接器以这个基准推导出 a 在运行时候的内存地址, 把这个地址写入 p 这个变量所对应的文件位置, 文件位置加载到内存后就对应 p 变量的地址, 写入的内容就是 p 初始化成什么内容. 所以, 可以说 p 的初始化是发生在链接期间的.
[解决办法]
1.
意思是这样,
不过应该不是说成"数据段和代码段可以使用不同的链接方式",
而是使用相同的链接方式, 代码段和数据段的重定位处理方法可能不同.
使用 -fPIC 选项: 代码段用位置无关代码, 数据段用重定位表.
不使用该选项: 代码段用重定位表, 数据段用重定位表.
2. 没有指针 p 的话, 数据段中就没有保存地址, 没有需要重定位的东西.
3. 见 6 楼, C 里面的全局变量是链接时候初始化的. (C++ 引入的构造函数打破了这个规律. 如果一个全局对象有构造函数, 它的构造函数只能是运行期来调用. 对象就是运行期初始化的了)
[解决办法]
1. 恩, 数据段没有共享内存的需求, 不需要.
3. C 语言还是编译链接的时候就初始好了的, 像这种代码, 在 C++ 里可以, 在 C 里面就不行:
int fff()
{
return 10;
}
void yyy()
{
static int x = fff();
}
static int z = fff();