2

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

我有一个多文件 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文件,这必然意味着根据包含语句出现的位置产生不同的内容。怎么会这样?

编译器是 g++ (GCC) 4.4.6

4

3 回答 3

1

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

你最好的机会来确定到底发生了什么,包括检查这些头文件中丢失符号的名称,并通过“工作”和“非工作”方式编译 calc.cc 获取预处理器输出,并比较两个文件。

于 2012-07-20T10:30:08.843 回答
1

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

例如,在上面的示例中,如果 file1.h 确实

#define lseek lseek64

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

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

于 2012-07-20T10:32:54.443 回答
0

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

于 2012-07-20T10:34:40.527 回答