GCC链接器抱怨对现有全局变量的未定义引用

时间:2016-05-02 14:26:02

标签: c++ gcc linker ld

我遇到GCC问题。它无法找到我的全局变量。我创建了一个示例C ++项目来隔离问题:

a.cpp:

#include "b.h"

const char * const g_test = "blah blah";

int main(){
    test();
    return 0;
}

b.cpp:

#include <iostream>
#include "a.h"

using namespace std;

void test(){
    cout << g_test;
}

A.H:

extern const char * const g_test;

b.h:

void test();

我这样编译:

$ g++ -o a.o -c a.cpp
$ g++ -o b.o -c b.cpp
$ g++ -o test a.o b.o
b.o: In function `test()':
b.cpp:(.text+0x7): undefined reference to `g_test'
collect2: error: ld returned 1 exit status

在最后一个命令中更改目标文件的顺序并不会改变任何内容。

为什么链接器会抛出错误?我本来希望只是创建一个可执行的打印&#34; blah blah&#34;,但不知怎的错误出现了。我没有看到它应该失败的原因。

2 个答案:

答案 0 :(得分:6)

由于const变量g_test只有内部链接,即只能在.cpp文件中使用它。为了给const变量提供全局链接(即使其可以从其他源文件中使用),你必须添加extern关键字,即:

#include "b.h"

extern const char * const g_test = "blah blah";

int main(){
    test();
    return 0;
}

或者,您可以在开头添加a.h。在这种情况下,编译器在翻译extern时会知道a.cpp前向声明。

然而,最好的解决方案是将g_test(没有extern关键字)的定义移到头文件中。原因是编译器以这种方式知道每个编译单元中g_test的定义,并且例如能够在编译时使用它来计算const表达式。

答案 1 :(得分:0)

最简单的解决方案是将关键字extern添加到您的定义中。我知道看起来很奇怪,extern通常使它成为前向声明而不是deffinition,但编译器仍将它视为定义(实例化),因为你给它一个值。

Quentin的评论(stolen from Quentin)中的链接是对原因的一个很好的解释。