【问题标题】:extern class: undefined reference when porting from gcc 3.x to 4.x外部类:从 gcc 3.x 移植到 4.x 时未定义的引用
【发布时间】:2011-03-03 23:45:54
【问题描述】:

我正在将一些可怕的遗留 C++ 代码从 gcc 3.x 移植到 4.x 头文件中有这样一个结构:

extern class ErrorLog
{
   . . .
} error_log, debug_log;

在 3.x 下它可以编译并且工作正常,但是在 4.x 下我得到很多形式的错误

undefined reference to `error_log'

undefined reference to `ErrorLog::log(ErrorLog::LogAttr const&, char const*, ...)'

【问题讨论】:

  • ErrorLog::log 在哪里实现? error_log 的实际定义在哪里?听起来您的 makefile 已更改,并且您缺少一个 .cpp 文件。
  • ErrorLog 的方法和实例 error_log 在 ErrorLog.cc 的其他地方实现。那是建立和联系的。相同的代码可以与 3.x 编译器链接

标签: c++ class reference undefined extern


【解决方案1】:

我认为这与我不久前提交给 GCC 的 bug report 有关。问题是,这是否定义了class ErrorLog 类型?我建议您将定义和声明分开,如下所示:

class ErrorLog{...};
extern ErrorLog error_log, debug_log;

大概class ErrorLog 也在其他地方定义了——理想情况下你应该改变它,使它只定义一次。

【讨论】:

  • 我尝试将定义和声明分开,但没有任何乐趣。我会再试一次。
  • 当你把它们分开时发生了什么?您是否收到编译器/链接器错误?什么错误?
  • 同样的事情发生了。完全没有区别。错误显示在链接阶段。但正如我所说,它适用于使用相同源代码和相同 makefile 的 3.x g++ 编译器。
  • 看起来链接器不匹配 class ErrorLog 的这个定义与定义 error_logdebug_log 时使用的定义。所以请确保class ErrorLog 只定义一次,然后再回复我们。
【解决方案2】:

Extern 是一个声明,而不是一个定义。因此,您只是声明了 name error_logdebug_log,而不是为它们分配内存位置。您需要在其他地方(可能在 .cpp 文件中)定义这些变量。

在包含您提到的头文件的源文件中执行此操作可能就足够了: ErrorLog error_log, debug_log;

在 extern 声明中包含整个类定义是很奇怪的。

【讨论】:

  • 抱歉,我无法掌握该站点使用的任何标记方法。对不起。有一个单独的文件 ErrorLog.cc #include "error.h" ErrorLog error_log = ErrorLog(ROOT_LOGGER_ID);` ErrorLog debug_log = ErrorLog(ROOT_LOGGER_ID);` void ErrorLog::log (const int level, const char* fmt, .. .) { ... }
  • 出于某种原因,它正在吞噬我的新台词。 #include "error.h" ErrorLog error_log = ErrorLog(ROOT_LOGGER_ID); ErrorLog debug_log = ErrorLog(ROOT_LOGGER_ID);void ErrorLog::log (const int level, const char* fmt, ...) { ... }
  • 在 cmets 中,您不能创建新段落……只能在原始问题和答案中。顺便说一句,你能在上面的帖子中回答我的问题吗? “当你把他们分开时发生了什么?......”
  • 分离类定义和外部对象声明没有区别。我想我需要尝试构建一个简单的测试用例。
  • 是的。我也认为我遗漏了一些相关信息......据我所见,TonyK 发布的解决方案应该可以工作。
【解决方案3】:

结果证明是一个简单的链接器排序问题。 error_log 定义在命令行早期列出的库中,但直到后来才使用。 4.x 链接器不能像 3.x 链接器那样跟踪定义的符号。在开始时添加 -Xlinker --whole-archive 解决了问题,尽管它自然会使对象膨胀。

更改顺序也可以,但存档集是自动生成的,因此如果不彻底重写 Makefile,这将更加困难。

【讨论】:

    猜你喜欢
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多