【C++】链接器及undefined reference的秘密

1、链接器

CC++要对函数和变量进行外部引用时,根据引用情况,链接器会选择不同的处理方法。如果还未遇到过这个函数或变量的定义,链接器会把它的标识符加到未解析的引用列表中,即undefined reference。如果链接器遇到过这个函数或变量的定义,那么这就是已解决的引用。

如果链接器在目标模块中不能找到函数或变量的定义,它将去查找库。库有某种索引方式,链接器不必到库里查找所有目标模块,而只需浏览索引。当链接器在库中找到定义后,就将整个目标模块而不仅仅是函数定义链接到可执行程序,注意仅仅是包含所需定义的目标模块加入链接,而不是整个库参加链接,否则程序会变得毫无意义的庞大。如果想尽量减小程序的长度,当构造自己的库时,可以考虑一个源代码文件只放一个函数。

链接器按指定的顺序查找文件,如果用户使用与库函数同名的函数,把带有这种函数的文件插到库文件名列表之前,就能用它自己的函数取代库函数。由于在找到库文件之前,链接器已先用用户所给定的函数来解释引用,因此被使用的是用户的函数额不是库函数。注意,有时候可能需要这么做,但这也可能是一个bug,并且C++名字空间禁止这样做。

最后,链接器在目标模块或库中没有找到所需的定义时,就抛出错误undefined reference,稍后介绍导致错误undefined reference的几种常见情况。

当创建一个C/C++可执行程序时,链接器会默认链接某些模块。其中之一是启动模块,它包含了对程序的初始化例程。初始化例程是开始执行C/C++程序时必须首先执行的一段程序,建立堆栈并初始化程序中的某些变量。链接器总是从标准库中查找程序中调用的经过编译的标准函数,由于标准库总可以被找到,所以只要在程序中包含所需的头文件,就可以使用库中的任何模块,并且不必告诉链接器去找标准库。如果使用附加的库,必须把该库文件名添加到由链接器处理的列表文件中。

2、undefined reference

C/C++程序开发中,undefined reference是一个经常会遇到的错误,下面总结了导致这个错误的几种常见情况。

(1)使用了一个确实未定义的函数,在当前模块和外部库中都没有定义。
(2)使用了外部库中的函数,但没有链接外部库。
(3)使用了外部库中的函数,链接了外部库,但链接顺序有误,从上面的对链接器的介绍可以看出链接器解析引用的规则,正确的做法是将包含了函数定义的外部库名放到使用了这个函数定义的模块名的后面。
(4)还有一个较为隐蔽的错误,CC++中的同名函数的编译结果是不同的,编译结果中,C++中的函数支持重载而带有参数类型信息,C中的函数则没有参数类型信息,在C++中调用C代码中的函数自然是没有问题的,但是,在C中调用C++代码中的函数就有问题了,找不到需要的函数定义,常见的做法是在这个函数的定义和声明时都使用extern "C",表明这是一个C函数,以C函数的方式去编译,还有很多其它技巧,可以在实战中摸索总结。

你可能感兴趣的:(编程语言)