Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ g++;无法将.o文件链接到可执行文件中_C++_Linker_G++_Clang_Linker Errors - Fatal编程技术网

C++ g++;无法将.o文件链接到可执行文件中

C++ g++;无法将.o文件链接到可执行文件中,c++,linker,g++,clang,linker-errors,C++,Linker,G++,Clang,Linker Errors,我正在用课本上的一个示例练习来学习。我只需要编译、链接和运行以下3个文件: //file my.h extern int foo; void print_foo(); void print(int); h是一个简单的头文件,它声明了两个函数和一个“全局”int foo,没有初始值 //file my.cpp #include "my.h" #include "std_lib_facilities.h" //not included but not source of error void p

我正在用课本上的一个示例练习来学习。我只需要编译、链接和运行以下3个文件:

//file my.h
extern int foo;
void print_foo();
void print(int);
h是一个简单的头文件,它声明了两个函数和一个“全局”int foo,没有初始值

//file my.cpp
#include "my.h"
#include "std_lib_facilities.h" //not included but not source of error

void print_foo()
{
    cout << foo << endl;
}

void print(int i)
{
    cout << i << endl;
}
它创建了两个对象文件my.o和use.o。我使用以下命令链接它们:

g++ -o myprog my.o use.o
告诉我这个错误:

Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      print_foo() in my.o
      _main in use.o
     (maybe you meant: __Z9print_foov)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我试过把

int foo;
进入我的.h而不是

extern int foo;
这给了我同样的错误

我试过使用

-std=c++11
导致相同错误的标志

我正在使用MacBook Pro和最新的macOS(事实上刚刚更新),如果这有助于解释错误消息的话

我尝试初始化foo,但没有改变任何东西

另外,我尝试过更新命令行工具,同样的错误

据我所知,错误告诉我,即使my.h包含在这两个文件中,也没有人可以使用foo变量(它调用_foo)实现任何函数,尽管它在my.h中显式声明。我的猜测是链接器在引擎盖下使用了错误的名称,这使得链接到可执行文件是不可能的。这是因为错误中提到了

__Z9print_foov
在任何文件中都不存在

在这一点上,它几乎像是一个g++或macOS/命令行工具错误。我不想每次都添加声明,因为这样会产生重复的符号错误。将my.cpp和use.cpp放在一个文件中可能会正确链接,但我需要确保我可以实际链接多个cpp文件,因为我最终(希望)将使用需要链接的多个cpp文件。感谢您的帮助

我建议用两个命令编译
g++-Wall-cmy.cpp
(即给出一个
my.o
)和
g++-Wall-c use.cpp
(给出
use.o
),然后将程序链接到
g++my.o use.o-o myprog
。实际上,您应该编写一个(请参阅以获取灵感)并简单地运行
make

您的翻译单元
my.cpp
use.cpp
都在声明一些
extern-int-foo从未定义的变量。因此,您需要在一个文件中定义它(但不能在其他文件中!),例如,可能需要单独添加(到
my.cpp

(没有
extern
)或者甚至有一些明确的初始值,例如
intfoo=34

这是因为错误提到了一个不存在的
\uuuuz9print\ufoov

它是一个,在两个对象文件中都引用(但未定义)(另请参见)

在这一点上,它几乎像是一个g++或macOS/命令行工具错误

您不太可能在编译器工具中发现bug(这两个工具都经过了非常好的测试;因为它们都是数百万行的自由软件,它们确实存在残余bug,但是您赢得彩票的机会比受到编译器bug影响的机会要多)。我从1974年开始编写代码,这在我一生中只发生过一次。更现实的态度是更谦虚,在怀疑编译器或构建链之前,先对自己的代码(和知识)提出质疑

顺便说一句,总是先编译所有警告和调试信息(例如
g++-Wall-g
,也可能
-Wextra
)。使用
gdb
调试器。当您确信您的代码没有bug时,您可以通过要求编译器对其进行基准测试(因此使用
g++-Wall-O2
也可以使用
-g
进行编译)


请阅读维基页面。深入您的(另请参见和标准,例如草稿)了解声明和定义某些变量或函数之间的区别。通常,您会在一些公共标题(包含在几个翻译单元中)中声明一个全局
extern
变量,并在其他地方定义一次,但最好的做法是避免使用大量全局变量。另请参见新变量

在此声明一个变量:

extern int foo;
cout << foo << endl;
然后使用变量:

extern int foo;
cout << foo << endl;

cout声明int-foo;在my.cpp中;成功了!谢谢你的帮助。但是,如果变量是在头文件中声明的,因此在包含它的.cpp文件中声明的(除非我遗漏了什么),我不理解链接器为什么会出现问题。如果要在.cpp文件中再次声明extern int foo,那么在头文件中声明extern int foo有什么意义?为了惯例?我不认为外星人有什么特别的,但仍然好奇,所以我没有这个问题了。阅读更多的C++书籍关于声明变量和定义之间的差异。bug的评论更多的是出于挫败感,而不是其他原因,并不打算破坏进入gcc的努力哈哈。我肯定会努力变得更谦虚。谢谢你花时间给我的建议不仅仅是回答问题!我阅读了一些文档,意识到即使没有任何初始化值,普通的int-foo也算作声明和定义,而头中的extern-int-foo是在没有定义的情况下声明的,因此没有定义,导致了我的错误在标题中(包含在多个翻译单元中),并有一个
.cpp
文件声明
foo
。另请参见内联变量。
cout << foo << endl;