包含语句的顺序如何在链接步骤中起作用?

时间:2012-07-20 10:26:06

标签: c++ linker include

我无法解释在链接代码时我看到的行为。也许有人知道发生了什么......

我有一个多文件C ++项目,它使用GNU automake工具作为其构建系统(全部在Linux上)。

将源文件和头文件(让我们称之为util.ccutil.h)添加到项目并使用已存在的源文件(calc.cc)从新添加的函数中调用函数后文件我得到链接错误取决于include语句出现的位置。我再说一遍:错误发生在链接步骤,编译运行正常!!

示例:

在将新的include语句放在预先存在的语句的末尾时出现错误,例如:

calc.cc:

#include "file1.h"
#include "file2.h"
#include "file3.h"
#include "file4.h"
#include "util.h"   // new header

此版本编译良好。但链接会产生错误(未找到符号)!!

现在,将此更改为

#include "util.h"   // new header
#include "file1.h"
#include "file2.h"
#include "file3.h"
#include "file4.h"

然后编译和链接运行正常!

由于链接器只读取.o文件,因此这必须意味着根据include语句的出现位置生成不同的内容。怎么会这样?

编译器是g ++(GCC)4.4.6

3 个答案:

答案 0 :(得分:1)

有可能util.h有一个#define,可以改变其他一个文件的行为。

确定正在进行的操作的最佳机会是检查缺少符号名称的头文件,并从编译calc.cc获取预处理器输出“工作”和“非工作”方式,并比较这两个文件。

答案 1 :(得分:1)

简单的头文件可以(重新)定义可以改变后续宏的解释的宏。

例如,在上面的示例中,如果file1.h执行

#define lseek lseek64

和util.h有一个调用lseek的内联函数,然后根据include顺序生成的目标代码将有一个符号引用lseek或lseek64。

这就是为什么项目倾向于首先包含config.h(由autoconf生成)的规则。

答案 2 :(得分:0)

你是绝对正确的:在这两种情况下会产生不同的目标代码。正如@hmjd所指出的那样,很可能在util.h中有一个宏,其中一个(.h或.c)文件使用,并且任何未声明的,被称为标识符的函数都被编译器认为是函数 - 这是这很可能是错误。