分类:
2012-01-10 23:03:20
原文地址:第三章 目标文件里有什么 作者:meiyang_stars
魔数
很多类型的文件,其起始的几个字节的内容是固定的(或是有意填充,或是本就如此)。因此这几个字节的内容也被称为魔数 (magic number),因为根据这几个字节的内容就可以确定文件类型。例如 FreeBSD 上 ELF 文件的 magic number 就是文件的前四个字节依次为"7f 45 4c 46",对应的ascii字符串即 "^?ELF"。tar 文件的 magic number 是从第257个字节起为 "ustar"。Unix 命令 "file" 应该就是利用这个原理工作的。
在一个Project里面,避免使用魔数(Magic Number)和魔字符串(Magic String)是相当必要的。通过定义的常量去access特定的字符串和数字也已经是软件开发的standard。那么是不是所有的数字和字符串都应该定义成常量呢?或许有朋友会认为所有的数字和字符串都应该定义成常量,但是我觉得,每个字符串确实是应该定义成常量的,但是对于数字而言,如果数字本身的语义没有得到延伸,那么就不应该定义成常量。譬如数组的index就不应该定义成变量。
符号修饰与函数签名
符号修饰:解决函数重载
函数签名:用于识别不同的函数,包含了一个函数的信息,包括函数名、参数类型、所在的类和名称空间等其他信息。
符号修饰和函数签名机制不光被用在函数上,C++中的全局变量和静态变量也有同样的机制。
#ifdef __cpluscplus
extern "C" {
#endif
void *memset(void *, int, size_t);
#ifdef __cpluscplus
}
#endif
如果当前编译单元式C++代码,那么memset会在extern "C"里面被声明;
如果是C代码,就直接声明。
强符号与弱符号
对于C/C++语言来说,编译器默认函数和初始化了的全局变量为强符号;为初始化的全局变量为弱符号。
比如有下面这段程序:
extern int ext;
int weak;
int strong = 1;
__attribute__((weak)) weak2 = 2;
int main()
{
return 0;
}
上面这段程序中,weak和weak2是弱符号,strong和main是强符号,而ext既非强符号也非弱符号,因为他是一个外部变量的引用。
针对强弱符号的概念,连接器就会按照如下规则处理与选择被多次定义的全局符号:
规则1:不允许强符号被多次定义;如果有多个强符号定义,则链接器报符号重复定义错误。
规则2:如果一个符号在某个目标文件中是强符号,则在其他文件中都是弱符号,那么选强符号。
规则3:如果一个符号在所有目标文件中都是弱符号,则选择其中占用空间最大的一个。
强引用与弱引用对于库来说非常有用。
在linux中可以使用strip命令来去掉ELF文件中的调试信息。