понедельник, 4 февраля 2008 г.

Тайна двух конструкторов...

Опять обнаружил странное дело. Начал вносить в свое ядро c++ код, и сразу же новая загадка...

Надо сказать, что я не очень люблю загадки. Я предпочитаю иметь полный контроль над кодом. И когда происходит что-то, чего я не понимаю, я начинаю нервничать, проклинать тот день, когда я решил переписать ядро частично на c++, и вообще...

class RandomGenerator {
public:
RandomGenerator ();
...
};

Ничем не примечательный класс, однако в коде мы видим следующее...

001039ac T RandomGenerator::RandomGenerator()
001039cc T RandomGenerator::RandomGenerator()

Начинаем выяснять почему...

$ nm Kernel-IA32
...
001039ac T _ZN15RandomGeneratorC1Ev
001039cc T _ZN15RandomGeneratorC2Ev

Наверное в двух экземплярах конструктора есть какой-то глубокий смысл. Но если обратить внимание на то, что они оба располагаются в одной секции, странно это. Я мог бы понять расположение двух одинаковых конструкторов в разных секциях, инициализация там, всякое такое, мог бы понять если бы у них было разное тело... Ан нет.

$ objdump -d Kernel-IA32
Disassembly of section .text:

001039ac <_ZN15RandomGeneratorC1Ev>:
1039ac: 53 push %ebx
1039ad: 83 ec 10 sub $0x10,%esp
1039b0: 8b 5c 24 18 mov 0x18(%esp),%ebx
1039b4: 68 71 15 00 00 push $0x1571
1039b9: 53 push %ebx
1039ba: e8 6f fe ff ff call 10382e <_ZN15RandomGenerator4initEm>
1039bf: 89 5c 24 20 mov %ebx,0x20(%esp)
1039c3: 83 c4 18 add $0x18,%esp
1039c6: 5b pop %ebx
1039c7: e9 70 fd ff ff jmp 10373c <_ZN15RandomGenerator6reloadEv>

001039cc <_ZN15RandomGeneratorC2Ev>:
1039cc: 53 push %ebx
1039cd: 83 ec 10 sub $0x10,%esp
1039d0: 8b 5c 24 18 mov 0x18(%esp),%ebx
1039d4: 68 71 15 00 00 push $0x1571
1039d9: 53 push %ebx
1039da: e8 4f fe ff ff call 10382e <_ZN15RandomGenerator4initEm>
1039df: 89 5c 24 20 mov %ebx,0x20(%esp)
1039e3: 83 c4 18 add $0x18,%esp
1039e6: 5b pop %ebx
1039e7: e9 50 fd ff ff jmp 10373c <_ZN15RandomGenerator6reloadEv>

Они полностью идентичны за исключением смещений. Загадка однако. Стоит отметить, что других конструкторов тоже два.

0010388c T RandomGenerator::RandomGenerator(unsigned long const*, unsigned long)
001039ec T RandomGenerator::RandomGenerator(unsigned long const*, unsigned long)

Как с этим бороться?

4 коммент.:

Анонимный комментирует...

Что за блин? Тебе не кажется, что гнус перемудрил что-то? А может ты забыл спрятать класс под условную компиляцию (#ifdef/#define#endif)? и он на каждый инклюд сгенерил код?

Вообще, с подобным встречаюсь впервые. В отличие от гнуса, ватком хоть и не очень оптимальный код порой генерит, но генерит правильно и экономит место ;).

Андрей Валяев комментирует...

У меня класс описан и реализован в одном cpp. И оптимизация включена (-Os).

В принципе он не сильно мешается, может с флагами что-то намудрил. будет время - я еще поковыряюсь.

Я пытался найти что означает C1 и C2, Но пока что-то не обнаружил инфы. Пишут что C - это const, при этом в названии функции нет ни слова про const.

Пока загадка...

Mike комментирует...

Сергей, интересная проблема, вы её решили? Она может повлиять на наши проекты.

В любом случае, линкеру, похоже, всё равно, с каким экземпляром линковать ссылки. Надо просто брать первый.

Andrey Valyaev комментирует...

В следующем посте..
http://mdf-i.blogspot.com/2008/02/blog-post_04.html

Но избавиться от них помоему нельзя.
Я смирился и не интересовался более. :)