Во-первых, мы можем посмотреть на имеющейся информации, и использовать его для начала поиска. Поскольку вы используете Linux, это, скорее всего, символ GCC или Clang, который дает нам хорошее начальное место: мы можем искать информацию о схемах GNU mangling.
Далее, ищите шаблоны в символе. Существует несколько строк с одним номером и несколькими буквами, где число - это общее количество букв в строке; это, вероятно, указывает на то, что это имена.
Учитывая, что мы можем взять на себя символ ZN5Gnome5Glade3Xml6createERKSsRKN4Glib7ustringES7
, и разбить его на:
Z
N
5Gnome
5Glade
3Xml
6create
E
R
K
S
s
R
K
N
4Glib
7ustring
E
S
7
Теперь, согласно коверкая схему GNU3-4, описанной в PDF "Calling Conventions" (pg.38), имена закодированные как:
<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
не сгенерирует правильный символ, который предполагает ча nge либо в схеме манипуляции, либо в 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 было изменено, в результате изменений в схеме коверкание и/или библиотеки typenames. Итак, чтобы проверить это, я сделал небольшое тестирование.
// 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
s- и тело main()
, скомпилированный файл с опцией на -c
компилятор, и вывести список символов с nm main.o
. Хотя typeid
не соответствует символ, отображаемые nm
имена были:
// With macros commented out:
_ZN5Gnome5Glade3Xml6createERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN4Glib7ustringESD_
// With macros active:
_ZN5Gnome5Glade3Xml6createERKSsRKN4Glib7ustringES7_
Поскольку второй один идентичен символу, указанной в сообщении об ошибке, это указывает на то, что схема коверкание все та же, и Таким образом, решение этой проблемы является:
либо объектные файлы вы пытающиеся ссылки были собраны с разными версиями GCC (или любой GCC-совместимый компилятор вы используете), или один был составлен с _GLIBCXX_USE_CXX11_ABI
макро установлен на 0
, а другой нет.