【问题标题】:Finding the root cause of `undefined reference` error查找“未定义引用”错误的根本原因
【发布时间】:2017-03-18 19:29:39
【问题描述】:

我试图了解为什么我在链接过程中收到 undefined reference 错误:

/home/amirgon/projects/esp8266/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -L/home/amirgon/projects/esp8266/esp-open-sdk/sdk/lib -T/home/amirgon/projects/esp8266/esp-open-sdk/sdk/ld/eagle.app.v6.cpp.ld -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--start-group -lc -lgcc -lhal -lphy -lpp -lnet80211 -llwip -lwpa -lmain build/app_app.a -Wl,--end-group -o build/app.out
build/app_app.a(routines.o):(.text+0x4): undefined reference to `pvPortMalloc(unsigned int, char const*, int)'

gcc 抱怨找不到函数pvPortMalloc
但是,我可以确认libmain.a中存在这个函数!

在上面的命令行中,libmain 由-lmain 引用,库路径设置为-L/home/amirgon/projects/esp8266/esp-open-sdk/sdk/lib。 当我在该路径上从libmain.a 转储符号时,我可以找到标记为TpvPortMalloc,这意味着该符号在文本(代码)部分中:

/home/amirgon/projects/esp8266/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-nm -g /home/amirgon/projects/esp8266/esp-open-sdk/sdk/lib/libmain.a | grep pvPortMalloc
         U pvPortMalloc
0000014c T pvPortMalloc
         U pvPortMalloc

那么,我错过了什么吗? 尽管它存在于 libmain.a 中,但 gcc 找不到该函数的原因可能是什么?
如何进一步调试此错误?

【问题讨论】:

  • 需要在链接行上的 .o 文件之后获取库,我相信。顺序在链接中很重要。
  • @FredLarson --start-group / --end-group 不会解决这个问题吗?它应该迭代地解析符号,直到所有符号都被解析。
  • 我认为这仅适用于 .a 文件,不适用于 .o 文件。
  • @FredLarson 但命令行上没有 .o 文件。应用程序代码已经在build/app_app.a 上,这是--end-group 之前的最后一个库。
  • 哦。嗯,那我不知道。对不起。

标签: c gcc linker linker-errors elf


【解决方案1】:

混合使用 C++ 和 C 代码会导致您的问题。

这个错误:

undefined reference to `pvPortMalloc(unsigned int, char const*, int)'

并不是说找不到符号pvPortMalloc。它说找不到符号pvPortMalloc(unsigned int, char const*, int), 那是一个 C++ 符号。

这意味着您正在编译 C++ 代码的某个地方认为有一个 C++ pvPortMalloc 函数,其符号也包括其签名,但您只有一个 pvPortMalloc C 函数。

您的 C++ 代码可能包含一个非 C++ 干净的头文件,您需要执行以下操作:

extern "C" {
#include "some_header.h"
}

其中 some_header.h 是声明 pvPortMalloc 函数的头文件。

【讨论】:

  • 这就是问题所在。谢谢!
【解决方案2】:

不仅命令行上目标文件和库的顺序很重要,库中的目标文件的顺序也很重要。

解决引用的任何内容都必须在使用符号之后出现,否则您可能会遇到奇怪的链接问题。

您看到的效果是使用ar 构建的库和错误的目标文件顺序(某些.o 文件使用在某些.o 文件中定义的外部函数之前 在 lib 中使用此符号的那个)。

ranlib <libfile> 是通过为库中的所有对象创建索引来解决此问题的工具,应该可以解决此问题。

【讨论】:

  • 这是一个很好的建议,但问题不是这种情况。问题在于 C 和 C++ 代码的混合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-06
  • 2014-04-07
  • 2012-05-24
  • 2019-09-25
  • 2016-05-31
  • 1970-01-01
  • 2018-12-29
相关资源
最近更新 更多