链接静态C库与C++代码时出现“undefined reference to”错误

43

我有一个测试文件(只是为了链接测试),在这个文件中,我使用自己的malloc/freelibxmalloc.a重载了new/delete运算符。但是在链接静态库时,即使我改变了test.o-lxmalloc的顺序,仍然会出现“未定义引用”错误,但是其他链接该库的C程序都可以正常工作。我对这个问题感到困惑,并感谢任何线索。

错误信息:

g++ -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64 -c -o test.o test.cpp
g++ -m64 -O3 -L. -o demo test.o -lxmalloc
test.o: In function `operator new(unsigned long)':
test.cpp:(.text+0x1): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete(void*)':
test.cpp:(.text+0x11): undefined reference to `free(void*)'
test.o: In function `operator new[](unsigned long)':
test.cpp:(.text+0x21): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete[](void*)':
test.cpp:(.text+0x31): undefined reference to `free(void*)'
test.o: In function `main':
test.cpp:(.text.startup+0xc): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x19): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x24): undefined reference to `free(void*)'
test.cpp:(.text.startup+0x31): undefined reference to `free(void*)'
collect2: ld returned 1 exit status
make: *** [demo] Error 1

我的test.cpp文件:

#include <dual/xalloc.h>
#include <dual/xmalloc.h>
void*
operator new (size_t sz)
{
    return malloc(sz);
}
void
operator delete (void *ptr)
{
    free(ptr);
}
void*
operator new[] (size_t sz)
{
    return malloc(sz);
}
void
operator delete[] (void *ptr)
{
    free(ptr);
}
int
main(void)
{
    int *iP = new int;
    int *aP = new int[3];
    delete iP;
    delete[] aP;
    return 0;
}

我的Makefile

CFLAGS += -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64
CXXFLAGS += -m64 -O3
LIBDIR += -L.
LIBS += -lxmalloc
all: demo
demo: test.o
    $(CXX) $(CXXFLAGS) $(LIBDIR) -o demo test.o $(LIBS)
test.o: test.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
clean:
- rm -f *.o demo

3
你是否尝试使用 extern "C" { #include <dual/xalloc.h> ... }?这样可以使代码更通用。 - πάντα ῥεῖ
看起来像是一个很好的规范,但已经有一个了吗? - πάντα ῥεῖ
1个回答

78

但是其他C程序与此库链接时都可以正常工作。

你是否注意到,C和C++编译在对象文件级别上创建不同的符号名称?这被称为“name mangling”。
(C++) 链接器会将未定义的引用显示为错误消息中的解码符号,这可能会使您感到困惑。如果您使用 nm -u 检查您的 test.o 文件,您会发现所引用的符号名称与您的库中提供的名称不匹配。

如果您想使用由纯C编译器编译的外部链接函数,则需要将它们的函数声明包含在 extern "C" {} 块中,该块抑制了C ++名称混淆,适用于其中声明或定义的所有内容,例如:

extern "C" 
{
    #include <dual/xalloc.h>
    #include <dual/xmalloc.h>
}

更好的做法是,你可以像这样在头文件中包装你的函数声明:
#if defined (__cplusplus)
extern "C" {
#endif

/*
 * Put plain C function declarations here ...
 */ 

#if defined (__cplusplus)
}
#endif

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