如何解决这个未定义的符号。
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
答案 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::ustring
和Gnome::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
输出函数符号,然后注释掉前两个#include
和main()
的主体,使用{编译文件{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)没有这个问题。