GCC нм перечисляет несколько записей для метода

Нормально ли иметь несколько записей для одного метода, перечисленного по нм? Я запустил следующее:

nm -C myObjectFile.o | grep MyObject::

и получил следующее:

... stuff...
... stuff...
0000027e0 T MyObject::MyObject(MyDepend*)
0000027e0 T MyObject::MyObject(MyDepend*)
000000030 T MyObject::~MyObject()
000000000 T MyObject::~MyObject()
000000000 T MyObject::~MyObject()
000000060 T non-virtual thunk to MyObject::~MyObject()
000000020 T non-virtual thunk to MyObject::~MyObject()

Это кажется мне неправильным. Вам это кажется неправильным? Если да, можете ли вы уточнить, почему это неправильно и что может быть причиной этого? Если это верно только при определенных обстоятельствах, тогда я объясню больше о проблеме, которая заставляет меня смотреть на выходной сигнал нм, и мы можем перейти оттуда.

0

Решение

В некоторых случаях demangler будет демангулировать разные входы на один и тот же выход. Иногда это может слегка смущать, но, думаю, это делается, потому что в других случаях это менее запутанно; например, demangler используется gdb, и этот подход позволяет точкам останова на конструкторах делать правильные вещи без дополнительных усилий со стороны пользователя. Может быть, здесь возможно некоторое улучшение, если подумать и поработать.

Во всяком случае, вот простой пример:

class K
{
K ();
virtual ~K();
};

K::K() { }
K::~K() { }

Компилирование с -g а затем работает nm -C показывает результаты, аналогичные вашим:

$ nm -C q.o
U operator delete(void*)
0000000000000000 T K::K()
0000000000000000 T K::K()
0000000000000048 T K::~K()
0000000000000018 T K::~K()
0000000000000018 T K::~K()
0000000000000000 V typeinfo for K
0000000000000000 V typeinfo name for K
0000000000000000 V vtable for K
U vtable for __cxxabiv1::__class_type_info

Но давайте посмотрим, что произойдет, если мы побежим nm:

$ nm q.o
U _ZdlPv
0000000000000000 T _ZN1KC1Ev
0000000000000000 T _ZN1KC2Ev
0000000000000048 T _ZN1KD0Ev
0000000000000018 T _ZN1KD1Ev
0000000000000018 T _ZN1KD2Ev
0000000000000000 V _ZTI1K
0000000000000000 V _ZTS1K
0000000000000000 V _ZTV1K
U _ZTVN10__cxxabiv117__class_type_infoE

Здесь мы можем видеть более четко, что основные символы различны.

От этого мы можем перейти к C ++ ABI, за которым следует GCC; в частности к разделу о калечащих конструкторах и деструкторах. По историческим причинам это называется «Itanium» ABI, но на самом деле он используется (возможно, с небольшими вариантами) на всех платформах.

В этом разделе объясняются значения названий, хотя вам придется углубиться в документ, чтобы полностью понять. Основная идея заключается в том, что в реализации C ++ существует необходимость в разных точках входа для конструкторов и деструкторов; и это делается путем предоставления разных символов для разных точек входа.

1

Другие решения


По вопросам рекламы [email protected]