new
/delete
演算子をlibxmalloc.a
という独自のmalloc
/free
ライブラリでオーバーロードするテストファイル(リンクテスト用)があります。しかし、test.o
と-lxmalloc
の順序を変更しても、静的ライブラリをリンクするときに次のような「undefined reference to」エラーが発生し続けます。しかし、このライブラリをリンクする他の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
しかし、このライブラリをリンクする他のCプログラムではすべてがうまく機能します。
CとC++のコンパイルにより、オブジェクトファイルレベルで異なるシンボル名が作成されることに気づきましたか? 「 name mangling 」と呼ばれます。
(C++)リンカーは、エラーメッセージにデマングルシンボルとして未定義の参照を表示するため、混乱する可能性があります。 test.o
でnm -u
ファイルを調べると、参照されているシンボル名がライブラリで提供されているものと一致しないことがわかります。
プレーンCコンパイラを使用してコンパイルされた外部としてリンクされた関数を使用する場合は、内部で宣言または定義されたすべてのC++名マングリングを抑制するextern "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