未定义的引用错误,但库中存在该符号。

6
我会尽力为您翻译中文。以下是需要翻译的内容:

在下面的例子中,我收到了一个“未定义引用”的错误。我看到很多与此问题相关的问题,但相信我给出了一个剥离、可重现、概念性的例子,而不是其他问题中的具体问题。

dynlib.h:

void printMe_dyn();

dynlib.c:

#include <stdio.h>
#include "dynlib.h"

void printMe_dyn() {
  printf("I am execuded from a dynamic lib");
}

myapp.c:

#include <stdio.h>
#include "dynlib.h"

int main() 
{
    printMe_dyn();
    return 0;
}

构建步骤:

gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
gcc -Wall -L. -ldynlib myapp.c -o myapp

错误:

/tmp/ccwb6Fnv.o: In function `main':
myapp.c:(.text+0xa): undefined reference to `printMe_dyn'
collect2: error: ld returned 1 exit status

证明该符号在库中:

nm libdynlib.so | grep printMe_dyn
00000000000006e0 T printMe_dyn
  1. 我使用的编译器标志是否正确,用于构建动态库?
  2. 我提供的证明是否真的是无歧义的证明?
  3. 还有哪些方法可以采取来诊断这个问题?
3个回答

5

库的出现顺序很重要

引用在线GCC手册的说法:

在命令中写入此选项的位置很重要。链接器按照指定的顺序搜索和处理库文件和目标文件。因此,foo.o -lz bar.o会在文件foo.o之后但在bar.o之前搜索库z。如果bar.o引用了z中的函数,则这些函数可能无法加载。

您应该更改编译语句为:

gcc -o myapp -Wall -L. myapp.c -ldynlib 

告诉gcc在编译myapp.c时搜索已出现的符号需要在dynlib中存在。


5

补充说明一下,当使用gcc编译库并将其链接到c++项目时,可能会出现相同的行为。具体如下:

gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
g++ -o myapp -Wall -L. myapp.cpp -ldynlib

在这种情况下,原因是g++使用的名称重整技术。要关闭它,必须在C库中用extern "C"包装C函数原型。例如,可以按照以下方式进行操作:

dynlib.h:

#ifdef __cplusplus
extern "C"{
#endif
void printMe_dyn();
#ifdef __cplusplus
}
#endif

1
链接器命令行中库的顺序很重要。修复方法:
gcc -o myapp -Wall -L. myapp.c -ldynlib 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接