【问题标题】:... undefined reference to ... collect2: ld returned 1 exit status... 未定义对 ... collect2 的引用:ld 返回 1 个退出状态
【发布时间】:2012-08-02 20:28:34
【问题描述】:

我有以下 3 个文件:

错误.h

#ifndef error_h
#define error_h
#include <string>
#include <iostream>
#include <cstdio>
void Error(std::string msg);
#endif

错误.cpp

#ifdef error_h
#include "error.h"
void Error(std::string msg)
{
    std::cerr
     << "\n=========================================================\n"
     << msg
     << "\n=========================================================\n";
    exit(EXIT_FAILURE);
}
#endif

foobar.cpp

#include "error.h"
int main()
{
    for(int i=0; i<99; i++)
        if(i==55)
            Error("this works");
    return 0;
}

现在我做:

$ g++ -c error.cpp foobar.cpp
$ g++ error.o foobar.o -o exampleprogram

我得到:

foobar.o: In function `main':
foobar.cpp:(.text+0x4b): undefined reference to `Error(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status

我做错了什么?我需要了解什么才能解决这个问题,以及将来不提出问题的类似问题?谢谢!

【问题讨论】:

  • 现在我也意识到 exit(int) 在 cstdlib 中而不是在 cstdio 中

标签: c++ linker ld undefined-reference


【解决方案1】:

删除这个

#ifdef error_h

以及来自error.cpp 的相应#endif。否则,在这里:

$ g++ -c error.cpp foobar.cpp

error.cpp 基本上是空的。这是因为在那个阶段error_h 没有定义。因此,您没有编译实现(如果您在#ifdef 之前包含error.h 之前,它将起作用,但无论如何都没有理由在.cpp 文件中包含它)。

【讨论】:

    【解决方案2】:

    error_h 未在 error.cpp 中定义,因此您的所有文件内容都会被 #ifdef 删除。

    本质上,您将 error.cpp 编译为一个空文件。

    【讨论】:

      【解决方案3】:

      为什么error.cpp中有这些行?

      #ifdef error_h
        ...
      #endif
      

      由于未定义预处理器符号error_h,因此预处理器将省略error.cpp 的全部内容。删除这些行,您的程序将成功链接。

      您似乎对如何(以及为什么)使用#include 守卫存在误解。解释请参考this答案。

      另外,没有必要在 error.h 中包含 iostreamcstdio,因为该文件没有使用任何一个中声明的任何内容那些标题。这些文件应该包含在error.cpp中。

      【讨论】:

      • 谢谢!我最近做了很多“.cpp包括”的模板实现,我只是不假思索地输入了这些,并且一直忽略它们。您提到了 iostream 和 cstdio 包含...这是否意味着我必须分散一些包含?有些在 .h 中,有些在 .cpp 中?函数原型是否需要#include ?一般来说,没有一种方法可以捆绑 .h 和 .cpp 的所有包含吗?再次感谢。
      • @user1358 最佳实践是只包含该文件中实际需要的标题,所以是的,包含往往分散在各处。在 error.h 中包含两个标头并没有错,但是当您在 main.cpp 中包含 error.h 时,预处理器将包含从 main.cpp 创建的翻译单元中的文件和编译器也必须处理这些头文件。在小型项目中并不是真正的问题,但对于大型项目,这可能会显着影响构建时间。
      • 您的解释很有帮助。非常感谢。
      猜你喜欢
      • 2012-02-18
      • 1970-01-01
      • 2015-06-13
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 1970-01-01
      • 2011-08-26
      • 2013-06-01
      相关资源
      最近更新 更多