nm命令解决undefined reference to "xxx"

  nm 可以通过查看符号表查看so中是否定义了某个函数,这个特性可以用于解决如下情况:

           在某次编译过程中出现undefined reference to "xxx";

说明

           出现以上情况说明程序编译已经通过,但是在链接过程中"xxx"符号找不到来源(定义definition或说明declaration),往往出现在动态链接的过程中,需要在程序外部寻找到支持“xxx”的链接库。以某一次android ndk交叉编译过程中c++标准库缺失为例。

问题

third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::imbue(std::locale const&): error: undefined reference to 'std::locale::_M_get_facet(std::locale::id const&) const'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::imbue(std::locale const&): error: undefined reference to 'std::locale::_M_use_facet(std::locale::id const&) const'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::imbue(std::locale const&): error: undefined reference to 'std::locale::_M_use_facet(std::locale::id const&) const'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::imbue(std::locale const&): error: undefined reference to '__cxa_call_unexpected'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::imbue(std::locale const&): error: undefined reference to 'std::codecvt::id'
third/CRF++-0.58/encoder.o:encoder.cpp:function CRFPP::CRFEncoderThread::~CRFEncoderThread(): error: undefined reference to 'std::__node_alloc::_M_deallocate(void*, unsigned int)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_stringbuf, std::allocator >::~basic_stringbuf(): error: undefined reference to 'std::locale::~locale()'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_stringbuf, std::allocator >::~basic_stringbuf(): error: undefined reference to 'std::locale::~locale()'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_ostringstream, std::allocator >::~basic_ostringstream(): error: undefined reference to 'std::ios_base::~ios_base()'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_ostringstream, std::allocator >::~basic_ostringstream(): error: undefined reference to 'std::ios_base::~ios_base()'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_seek(long, int)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_unmap(void*, long)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_seek(long, int)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_unmap(void*, long)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_seek(long, int)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_unmap(void*, long)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_filebuf >::seekoff(long, int, int): error: undefined reference to 'std::_Filebuf_base::_M_unmap(void*, long)'
third/CRF++-0.58/encoder.o:encoder.cpp:function std::basic_stringbuf, std::allocator >::xsputn(char const*, int): error: undefined reference to 'std::__node_alloc::_M_allocate(unsigned int&)'

分析

       从终端打印能够看出这些未定义函数都在std命名空间下,但是在makefile里链接参数已经设置为 -lstdc++ -lsupc++,在网上找到的资料只能给出某个特定场景下的出错解决方式,但以下博客

         https://blog.csdn.net/andyhuabing/article/details/8591459

      提供了一个思路,可以使用android自带的nm命令在符号表中找到未定义的函数。

过程

     以函数bad_alloc() 和_M_open()为例

  1、使用nm命令查看supc++

 ~/tool/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/p
rebuilt/linux-x86_64/bin/arm-linux-androideabi-nm libgnustl_static.a | grep "bad_alloc"

bad_alloc.o:
00000000 T _ZNKSt9bad_alloc4whatEv
00000000 T _ZNSt9bad_allocD0Ev
00000000 T _ZNSt9bad_allocD1Ev
00000000 T _ZNSt9bad_allocD2Ev
00000000 D _ZTISt9bad_alloc
00000000 R _ZTSSt9bad_alloc
00000000 D _ZTVSt9bad_alloc
         U _ZNSt9bad_allocD2Ev
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD2Ev
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD1Ev
         U _ZTISt9bad_alloc
         U _ZTVSt9bad_alloc
         U _ZTISt9bad_alloc
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD1Ev
         U _ZTISt9bad_alloc
         U _ZTVSt9bad_alloc
         U _ZSt17__throw_bad_allocv
         U _ZTISt9bad_alloc
         U _ZTISt9bad_alloc
         U _ZSt17__throw_bad_allocv
         U _ZSt17__throw_bad_allocv
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD1Ev
00000000 T _ZSt17__throw_bad_allocv
         U _ZTISt9bad_alloc
         U _ZTVSt9bad_alloc


~/tool/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/p
rebuilt/linux-x86_64/bin/arm-linux-androideabi-nm libsupc++.a | grep "bad_alloc"


bad_alloc.o:
00000000 T _ZNKSt9bad_alloc4whatEv
00000000 T _ZNSt9bad_allocD0Ev
00000000 T _ZNSt9bad_allocD1Ev
00000000 T _ZNSt9bad_allocD2Ev
00000000 D _ZTISt9bad_alloc
00000000 R _ZTSSt9bad_alloc
00000000 D _ZTVSt9bad_alloc
         U _ZNSt9bad_allocD2Ev
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD2Ev
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD1Ev
         U _ZTISt9bad_alloc
         U _ZTVSt9bad_alloc
         U _ZTISt9bad_alloc
         U _ZTISt9bad_alloc
         U _ZNSt9bad_allocD1Ev
         U _ZTISt9bad_alloc
         U _ZTVSt9bad_alloc

  可以见到bad_malloc函数在libsupc++.a中和libgnustl_static.a中均有定义;但同样方式查看_M_open,没有定义,说明libsupc++.a和libgnustl_static.a不是要寻找的库;同样可以尝试链接到程序中查看程序是否编译完成。

     2、使用nm命令查看 libstlport_shared.so

 ~/tool/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/li
nux-x86_64/bin/arm-linux-androideabi-nm libstlport_shared.so | grep "bad_alloc"


00025bdc T _ZNKSt9bad_alloc4whatEv
00025bb0 T _ZNSt9bad_allocC1Ev
00025bb0 T _ZNSt9bad_allocC2Ev
00025bcc T _ZNSt9bad_allocD0Ev
00025bc8 T _ZNSt9bad_allocD1Ev
00025bc8 T _ZNSt9bad_allocD2Ev
0005fa34 D _ZTISt9bad_alloc
0005a9da R _ZTSSt9bad_alloc
0005fa0c D _ZTVSt9bad_alloc


~/tool/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/li
nux-x86_64/bin/arm-linux-androideabi-nm libstlport_shared.so | grep "_M_open"


000270f0 T _ZNSt13_Filebuf_base7_M_openEii
000270e8 T _ZNSt13_Filebuf_base7_M_openEPKci
00027010 T _ZNSt13_Filebuf_base7_M_openEPKcil

     可以大概确定 libstlport_shared.so是我需要的链接库

LFLAGS+=-L $(NDK_HOME)/sources/cxx-stl/stlport/libs/armeabi-v7a -lstlport_shared

3、编译完成

       将上述链接选项添加到makefile,编译通过。

你可能感兴趣的:(工欲善其事,必先利其器)