符号查找错误:.so.2未定义符号

时间:2016-07-13 14:19:05

标签: symbols

如何解决这个未定义的符号。

  

odroid @ odroid:〜/ flycapture.2.9.3.43_armhf / bin $ sudo ./FlyCap2   ./FlyCap2:符号查找错误:/usr/lib/libflycapturegui.so.2:未定义的符号: ZN5Gnome5Glade3Xml6createERKSsRKN4Glib7ustringES7

odroid@odroid:~/flycapture.2.9.3.43_armhf/bin$ sudo ldconfig -v | grep fly

/sbin/ldconfig.real: Path `/lib/arm-linux-gnueabihf' given more than once
/sbin/ldconfig.real: Path `/usr/lib/arm-linux-gnueabihf' given more than once
/sbin/ldconfig.real: /lib/arm-linux-gnueabihf/ld-2.23.so is the dynamic linker, ignoring
/sbin/ldconfig.real: /usr/lib/libflycapture.so.2 is not a symbolic link
/sbin/ldconfig.real: /usr/lib/libflycapturegui.so.2 is not a symbolic link

libflycapture.so.2 -> libflycapture.so.2.9.3.43
libflycapturegui.so.2 -> libflycapturegui.so.2.9.3.43
odroid@odroid:~/flycapture.2.9.3.43_armhf/bin$ ls -lah /usr/lib | grep fly

-rw-r--r--   1 root root 473K Jul 13 13:26 libflycapturegui.so
-rw-r--r--   1 root root 473K Jul 13 13:26 libflycapturegui.so.2
-rw-r--r--   1 root root 473K Jul 13 13:26 libflycapturegui.so.2.9.3.43
-rw-r--r--   1 root root 3.3M Jul 13 13:26 libflycapture.so
-rw-r--r--   1 root root 3.3M Jul 13 13:26 libflycapture.so.2
-rw-r--r--   1 root root 3.3M Jul 13 13:26 libflycapture.so.2.9.3.43

2 个答案:

答案 0 :(得分:0)

首先,我们可以查看可用信息,并使用它来开始搜索。当您使用Linux时,它很可能是GCC或Clang错位符号,它为我们提供了一个良好的起点:我们可以查找有关GNU修改方案的信息。

接下来,查找符号中的图案。有多个一个多个字母的字符串,其中数字是字符串中的字母总数;这可能表明这些都是名字。

考虑到这一点,我们可以使用符号ZN5Gnome5Glade3Xml6createERKSsRKN4Glib7ustringES7,并将其分解为:

Z
N
5Gnome
5Glade
3Xml
6create
E
R
K
S
s
R
K
N
4Glib
7ustring
E
S
7

现在,根据PDF "Calling Conventions"(第38页)中描述的GNU3-4修改方案,名称编码为:

<public name>    ::= _Z <qualified name>
<qualified name> ::= N [<simple name>]<sup>∞</sup><sub>2</sub> E
    There are a minimum of 2 "simple name" symbols.
<simple name>    ::= <name length> <name>
    "Name length" is a decimal number indicating the length of "name".
Nested names are listed inwards, with the leftmost one being the outermost.

我们可以用它来拼凑部分符号及其含义:

Symbol: _ZN5Gnome5Glade3Xml6createE
Means : The symbol's qualified name is "Gnome::Glade::Xml::create".
Note  : At least one underscore appears to have been dropped by the error message.

考虑到它之后的垃圾和名称本身,这是一个函数符号。因此,考虑到这一点,我们只需将符号提供给Google,然后获取a link to the class' reference.根据此链接,该函数定义为:

Class  :   Gnome::Glade::Xml
Section: "Static Public Member Functions"
Full declaration:
    static Glib::RefPtr< Xml >
    create (const std::string &filename, const Glib::ustring &root=Glib::ustring(),
            const Glib::ustring &domain=Glib::ustring())

要仔细检查,我们可以使用该参数列表确定函数的错位名称:

static Glib::RefPtr< Xml >
Gnome::Glade::Xml::create (const std::string &filename,
                           const Glib::ustring &root=Glib::ustring(),
                           const Glib::ustring &domain=Glib::ustring());

直接将它放在一个简单的C ++程序中(使用Glib::RefPtr<T>Glib::ustringGnome::Glade::Xml的虚拟类),然后输出typeid(Gnome::Glade::Xml::create).name()cout生成正确的符号,这表明修改方案或ABI的变化。更具体地说,std::string被标记为NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE,而不是预期的Ss。在a bit of digging around之后,我发现这是由于GCC 5.1及更高版本的更改,其中宏_GLIBCXX_USE_CXX11_ABI表示使用新的string(和新名称)而不是旧版本一。这也可能表明问题的原因(见本文末尾)。

因此,考虑到这一点,最好使用旧方案手动破坏函数的名称,并查看它是否与符号匹配。

<public name> ::= <simple or qualified name> [<parameter type>]<sup>∞</sup><sub>1</sub>
    There is a minimum of 1 "parameter type" symbols.

Name      : Gnome::Glade::Xml::create
Parameters:
    const std::string&   : RKSs
        "RK" is "Reference (R), const (K)", and "Ss" is a special symbol for std::string.
    const Glib::ustring& : RK4Glib7ustringE
        "RK" is followed by the type's "qualified name".
    const Glib::ustring& : RK4Glib7ustringE

由于第三个参数是第三个参数的副本,因此它使用缩写规则,其中Sx_是缩写符号。根据PDF,每个用户定义的类型名称,命名空间名称和非简单类型都分配了一个缩写,但实体名称本身不是。因此...

S0_ : 5Gnome
S1_ : 5Glade
S2_ : 3Xml
S3_ : Ss
S4_ : RKSs
S5_ : 4Glib
S6_ : 7ustring
S7_ : RK4Glib7ustringE

因此,第三个参数是S7_。考虑到这一点,最终的符号是:

Name          : _ZN5Gnome5Glade3Xml6createE
Parameter list: RKSsRKN4Glib7ustringES7_
    Parameters:
        RKSs              : const std::string&
        RKN4Glib7ustringE : const Glib::ustring&
        S7_               : const Glib::ustring&
Symbol        : _ZN5Gnome5Glade3Xml6createERKSsRKN4Glib7ustringES7_
    Two underscores were apparently dropped somewhere, one on each end.

将其提供给实用程序站点Demangler.com会生成以下符号的符号:

Gnome::Glade::Xml::create(std::string const&, Glib::ustring const&, Glib::ustring const&)

由于PDF声明返回类型不包含在正常函数的修改方案中,因此这似乎是正确的。

现在,如上所述,ABI已更改,导致修改方案和/或库类型名称发生更改。所以,为了检查这个,我做了一些测试。

// main.cpp
//#undef  _GLIBCXX_USE_CXX11_ABI
//#define _GLIBCXX_USE_CXX11_ABI 0

//#include <iostream>
//#include <typeinfo>
#include <string>


namespace Glib {
    template<typename T>
    class RefPtr {};

    class ustring {};
}

namespace Gnome {
    namespace Glade {
        class Xml {
          public:
            static Glib::RefPtr< Xml >
            create (const std::string &filename,
                    const Glib::ustring &root=Glib::ustring(),
                    const Glib::ustring &domain=Glib::ustring());
        };
    }
}

Glib::RefPtr< Gnome::Glade::Xml >
Gnome::Glade::Xml::create (const std::string &filename,
                           const Glib::ustring &root /*=Glib::ustring()*/,
                           const Glib::ustring &domain /*=Glib::ustring()*/) {
                               return Glib::RefPtr<Gnome::Glade::Xml>();
                           }

int main() {
//    std::cout << typeid(const std::string&).name() << std::endl;
//    std::cout << typeid(Gnome::Glade::Xml::create).name() << std::endl;

//    std::cout << typeid(std::string).name() << std::endl;
}

通过使用此代码,我首先使用typeid输出函数符号,然后注释掉前两个#includemain()的主体,使用{编译文件{1}}编译器选项,并输出带有-c的符号列表。虽然nm main.o与符号不匹配,但typeid显示的名称为:

nm

由于第二个与错误消息中提到的符号相同,这表明修改方案仍然相同,因此解决问题的方法是:

您尝试链接的目标文件是使用不同版本的GCC(或您正在使用的GCC兼容编译器)编译的,或者是在// With macros commented out: _ZN5Gnome5Glade3Xml6createERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN4Glib7ustringESD_ // With macros active: _ZN5Gnome5Glade3Xml6createERKSsRKN4Glib7ustringES7_ 宏设置为{的情况下编译的文件。 {1}}而另一个则没有。

答案 1 :(得分:0)

我在尝试在arch linux上安装flycapture时遇到了同样的问题。最后我发现有一个更新版的flycapture(2.11.3.121)没有这个问题。