C++ 代码中对 C 函数的未定义引用
undefined reference to c functions in c++ code
我有一个奇怪的问题:下面的代码完美编译。
src.cpp:
extern "C" {
#include "header.h"
}
void A::Execute() {
B::Instance().Reset(ix);
c_func(ix);// this is c functions declared in header.h
C::Instance().Erase(ix);
}
但是当我注释掉 c_funk() 时,我在所有使用 header.h 文件中的 c 函数的地方都出现了链接错误。
有了这个小改动:
void A::Execute() {
B::Instance().Reset(ix);
//c_func(ix);// this is c function declared in header.h
C::Instance().Erase(ix);
}
我得到:对 c_func() 的未定义引用。
任何想法如何解决它?谢谢
更新:
我在 header.h 中添加了一个虚拟函数:foo_for_linkage_problem();
并以这种方式解决了问题。据我了解,链接器会尝试进行一些优化来解决此问题。新代码:
void A::Execute() {
B::Instance().Reset(ix);
foo_for_linkage_problem();// this is c empty function declared in header.h
C::Instance().Erase(ix);
}
tldnr:您在向 linker 提供库的顺序上遇到问题。
我想我知道哪里出了问题。假设您有四个文件:
main.c
:
#include <stdio.h>
int a();
int b();
int main()
{
printf("%d\n", a());
printf("%d\n", b());
return 0;
}
main2.c
:
#include <stdio.h>
int a();
int b();
int main()
{
//printf("%d\n", a());
printf("%d\n", b());
return 0;
}
a.c
:
int a()
{
return 67;
}
b.c
:
int a();
int b()
{
return a()+5;
}
我们创建 liba.a
和 libb.a
:
gcc a.c -c -o a.o
gcc b.c -c -o b.o
ar rcs liba.a a.o
ar rcs libb.a b.o
现在我们编译我们的exec:
gcc main.c liba.a libb.a -o test
一切正常
gcc main2.c liba.a libb.a -o test
我得到:
libb.a(b.o): In function `b':
b.c:(.text+0xa): undefined reference to `a'
collect2: error: ld returned 1 exit status
让我们检查一下我的库中有哪些符号 provides/requires:
$nm liba.a
a.o:
0000000000000000 T a
符号类型T
表示这个库有文件a.o
提供符号a
$nm libb.a
b.o:
U a
0000000000000000 T b
libb.a
包含提供符号 b
但需要符号 a
的文件 b.o
linker 在被询问时不包括整个静态库。它看起来需要 .o
个文件,而只需要 link 个文件。因此,您提供文件的顺序至关重要。
当执行以下命令时,main.c
被编译并且它需要 a
和 b
符号。当 linker 获取 liba.a
库时,它 links a.o
文件,因为它提供 a
符号。当 linker 获得 libb.a
库时,它 links b.o
文件,因为它提供 b
符号。一切正常。
gcc main.c liba.a libb.a -o test
当执行 main2 命令时,main2.c
被编译,它只需要 b
个符号。当 linker 获得 liba.a
时,它不会 link a.o
因为根本不需要 a
。然后 linker 获取 libb.a
库它 links b.o
文件因为它提供 b
符号。但是b.o
文件需要符号a
,来不及linka.o
,liba.a
已经处理了。请注意,当
我切换库它会干净地编译:
gcc main2.c libb.a liba.a -o test
我有一个奇怪的问题:下面的代码完美编译。
src.cpp:
extern "C" {
#include "header.h"
}
void A::Execute() {
B::Instance().Reset(ix);
c_func(ix);// this is c functions declared in header.h
C::Instance().Erase(ix);
}
但是当我注释掉 c_funk() 时,我在所有使用 header.h 文件中的 c 函数的地方都出现了链接错误。
有了这个小改动:
void A::Execute() {
B::Instance().Reset(ix);
//c_func(ix);// this is c function declared in header.h
C::Instance().Erase(ix);
}
我得到:对 c_func() 的未定义引用。
任何想法如何解决它?谢谢
更新:
我在 header.h 中添加了一个虚拟函数:foo_for_linkage_problem();
并以这种方式解决了问题。据我了解,链接器会尝试进行一些优化来解决此问题。新代码:
void A::Execute() {
B::Instance().Reset(ix);
foo_for_linkage_problem();// this is c empty function declared in header.h
C::Instance().Erase(ix);
}
tldnr:您在向 linker 提供库的顺序上遇到问题。
我想我知道哪里出了问题。假设您有四个文件:
main.c
:
#include <stdio.h>
int a();
int b();
int main()
{
printf("%d\n", a());
printf("%d\n", b());
return 0;
}
main2.c
:
#include <stdio.h>
int a();
int b();
int main()
{
//printf("%d\n", a());
printf("%d\n", b());
return 0;
}
a.c
:
int a()
{
return 67;
}
b.c
:
int a();
int b()
{
return a()+5;
}
我们创建 liba.a
和 libb.a
:
gcc a.c -c -o a.o
gcc b.c -c -o b.o
ar rcs liba.a a.o
ar rcs libb.a b.o
现在我们编译我们的exec:
gcc main.c liba.a libb.a -o test
一切正常
gcc main2.c liba.a libb.a -o test
我得到:
libb.a(b.o): In function `b':
b.c:(.text+0xa): undefined reference to `a'
collect2: error: ld returned 1 exit status
让我们检查一下我的库中有哪些符号 provides/requires:
$nm liba.a
a.o:
0000000000000000 T a
符号类型T
表示这个库有文件a.o
提供符号a
$nm libb.a
b.o:
U a
0000000000000000 T b
libb.a
包含提供符号 b
但需要符号 a
b.o
linker 在被询问时不包括整个静态库。它看起来需要 .o
个文件,而只需要 link 个文件。因此,您提供文件的顺序至关重要。
当执行以下命令时,main.c
被编译并且它需要 a
和 b
符号。当 linker 获取 liba.a
库时,它 links a.o
文件,因为它提供 a
符号。当 linker 获得 libb.a
库时,它 links b.o
文件,因为它提供 b
符号。一切正常。
gcc main.c liba.a libb.a -o test
当执行 main2 命令时,main2.c
被编译,它只需要 b
个符号。当 linker 获得 liba.a
时,它不会 link a.o
因为根本不需要 a
。然后 linker 获取 libb.a
库它 links b.o
文件因为它提供 b
符号。但是b.o
文件需要符号a
,来不及linka.o
,liba.a
已经处理了。请注意,当
我切换库它会干净地编译:
gcc main2.c libb.a liba.a -o test