我无法解释在链接代码时我看到的行为。也许有人知道发生了什么......
我有一个多文件C ++项目,它使用GNU automake工具作为其构建系统(全部在Linux上)。
将源文件和头文件(让我们称之为util.cc
和util.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
答案 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)文件使用,并且任何未声明的,被称为标识符的函数都被编译器认为是函数 - 这是这很可能是错误。