12、深入理解计算机系统笔记:程序链接(1)

1、静态链接

wps_clip_image-31780

注:链接器将重定位目标文件(relocatable object files)组合成一个可执行目标文件。cpp(c previous processor,C预处理器)cclC编译器);as(汇编器)

2、为了创建静态链接,链接器完成两个主要任务:

1)符号解析(symbol resolution):将每个符号引用和一个符号定义联系起来。

2)重定位(relocation):编译器和汇编器生成从0地址开始的代码和数据节。链接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些节。

3、目标文件有三种形式

Relocatable object file(可重定位目标文件). Contains binary code and data in a

form that can be combined with other relocatable object files at compile time to create

an executable object file.

Executable object file(可执行目标文件). Contains binary code and data in a form

that can be copied directly into memory and executed.

Shared object file(共享目标文件). A special type of relocatable object file that can

be loaded into memory and linked dynamically, at either load time or run time.

    可重定位目标文件的格式,可以参见第7章,7.4Relocatable Object Files》。

4、符号解析

C++Java中能使用重载函数,是因为编译器将每个惟一的方法和参数列表组合编码成一个对链接器来说惟一的名字。这种编码过程叫做毁坏(mangling),而相反的过程叫恢复(demangling)。

C++Java使用的是兼容的毁坏策略。一个已毁坏类的名字是由名字中字符的整数数量,后面跟原始名字组成的。比如类Foo被编译成3Foo;方法被编译成:原始方法名 + __ + 已毁坏的类名+ 再加上每个类参数的一个字母。如Foo::bar(int, long)被编译成bar__3Fooil。毁坏全局变量和模板名字的策略是相似的。

5、链接器如何解析多处定义的全局符号

函数和已初始化的全局变量是强符号(strong);未初始化的全局变量是弱符号(weak)。

Given this notion of strong and weak symbols, Unix linkers use the following rules

for dealing withmultiplydefined symbols:

Rule 1: Multiple strong symbols are not allowed.

Rule 2: Given a strong symbol and multiple weak symbols, choose the strong symbol.

Rule 3: Given multiple weak symbols, choose any of the weak symbols.

示例程序1

//test1.cpp
#include <iostream>
#include "string"
#include "stdio.h"

using namespace std;

int x = 15213;
void f();
int main()
{
f();
cout << x << endl;
return 0;
}
//test2.cpp
extern int x;
void f()
{
x = 15212;
}

说明:在教材中,作者说x的值由15213变成15212是由于规则起了作用,说x的值一开始时选择15213是选择强符号。我感觉:很明显的,在程序中,test1x是定义,而test2x是声明,没有其它的理由。

示例程序2

//test1.cpp
#include <iostream>
#include "string"
#include "stdio.h"

using namespace std;

int x = 15213;
int y = 15212;
void f();
int main()
{
f();
cout << hex << x << " " << y <<endl;
return 0;
}
//test2.cpp
extern double x;
void f()
{
x = -0.0;
}

说明:在这个程序中,把变量定义中int,而声明成double,这是一个很危险的错误,在大型程序中也不易发掘,应当引起注意。

6unix中,静态库以一种称为存档(archive)的特殊文件格式存放在磁盘中。存档文件是一组连接起来的可重定位目标文件的集合,有一个头部描述每个成员目标文件的大小和位置;后辍名为.a

wps_clip_image-6864

7、链接器使用静态库来解析引用的过程

在符号解析时,链接器从左到右按照它们在编译器驱动程序命令行上出现的顺序来扫描可重定位目标文件和存档文件。在扫描中,链接器维持一个可重定位目标文件的集合E,这个集合中的文件会被合并起来形成可执行文件,和一个未解析(引用了但是尚未定义的符号)的符号集U,以及一个在前面输入文件中已定义的符号集合D。初始化,EUD都是空的。

wps_clip_image-25635

注:第二节中第一行的against,在中文版本中翻译为“和”,我觉得是不准确的。

against的意思有:与...方向相反,逆着,顶着;对...不利;反对,反抗;...为标准;和...比,和...对照,以...为背景等。这里我觉得取...比,和...对照比较好。

<Computer Systems:A Programmer's Perspective>

原文地址:https://www.cnblogs.com/mydomain/p/2080981.html