GCC 链接器抱怨对现有全局变量的未定义引用
GCC linker complains about undefined reference to existing global variable
我对 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
在上一个命令中更改目标文件的顺序不会改变任何内容。
为什么链接器会抛出错误?我原本希望只创建一个可执行打印 "blah blah",但不知何故出现了错误。我看不出它应该失败的任何原因。
作为 const 变量 g_test
只有内部链接,即只能在它定义的 .cpp 文件中使用。为了给一个 const 变量全局链接(即使其可从其他源文件使用),您必须添加 extern
关键字,即:
#include "b.h"
extern const char * const g_test = "blah blah";
int main(){
test();
return 0;
}
或者您可以在开头包含 a.h
。在这种情况下,编译器在翻译 a.cpp
.
时知道 extern
前向声明
然而,最好的解决方案是将 g_test
的定义(不带 extern
关键字)移动到头文件中。原因是通过这种方式,编译器知道每个编译单元中 g_test
的定义,例如能够在编译时使用它来评估 const 表达式。
最简单的解决方案是将关键字 extern
添加到您的定义中。我知道这看起来很奇怪,extern
通常使它成为前向声明而不是定义,但编译器仍会将其视为定义(实例化),因为您给它赋值。
Quentin 的评论 (stolen from Quentin) 中的 link 很好地解释了原因。
我对 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
在上一个命令中更改目标文件的顺序不会改变任何内容。
为什么链接器会抛出错误?我原本希望只创建一个可执行打印 "blah blah",但不知何故出现了错误。我看不出它应该失败的任何原因。
作为 const 变量 g_test
只有内部链接,即只能在它定义的 .cpp 文件中使用。为了给一个 const 变量全局链接(即使其可从其他源文件使用),您必须添加 extern
关键字,即:
#include "b.h"
extern const char * const g_test = "blah blah";
int main(){
test();
return 0;
}
或者您可以在开头包含 a.h
。在这种情况下,编译器在翻译 a.cpp
.
extern
前向声明
然而,最好的解决方案是将 g_test
的定义(不带 extern
关键字)移动到头文件中。原因是通过这种方式,编译器知道每个编译单元中 g_test
的定义,例如能够在编译时使用它来评估 const 表达式。
最简单的解决方案是将关键字 extern
添加到您的定义中。我知道这看起来很奇怪,extern
通常使它成为前向声明而不是定义,但编译器仍会将其视为定义(实例化),因为您给它赋值。
Quentin 的评论 (stolen from Quentin) 中的 link 很好地解释了原因。