inline ctor & VFT init

Тема в разделе "LANGS.C", создана пользователем sn0w, 20 июл 2018.

  1. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    Господа, тут вдарился в реверс плюсов, ну и периодически возникают всяческие вопросы.
    есть такой код:

    Код (C++):
    1. class IFace
    2. {
    3.     int a, b, c;
    4. public:
    5.     virtual int Test();
    6.     //IFace();
    7.     IFace()
    8.         :a(0), b(0), c(0) {}
    9. };
    10.  
    11. //IFace::IFace()
    12. //:a(0), b(0), c(0) {}
    13.  
    14. IFace* SetupInterface() // dummy
    15. {
    16.     return nullptr;
    17. }
    18.  
    19. void InstallHookStandalone()
    20. {
    21.     IFace *pInterface = SetupInterface(); // external (another binary)
    22.     pInterface->Test();
    23. ...
    24. }
    в указанном случае линкуется нормально, но если инлайн-конструктор закомментить, а обычный(с телом вне класса) раскомментить - то тут линкер заругается на то что у IFace::Test() нету определения.
    происходит это, как я понимаю, потому что появился код конструктора с неявной установкой поинтера VFT, но кроме того, эту самую VFT тоже нужно загенерить и заполнить адресами.
    а с другой стороны, получается что при использовании инлайн конструктора код попросту некуда присобачить и он отбрасывается. поэтому и анресолведа нет.
    правильно понимаю?
     
  2. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    sn0w, что тебя удивляет?
    У тебя у Test() и так нет определения, при этом она обьявлена как виртуальная процедура с определением по умолчанию, которое отсутствует. То что компилер в одном случае ругается, а во втором нет это вопрос открытый, по логике в обоих должен ругаться. Но видимо в твоем примере без создания инстанса объекта это прокатывает. Полностью виртуальные процедуры могут быть определены в другом бинарном модуле, поэтому вполне нормально, что определение отсутствует и компилятор это съедает, но не в твоем случае с наличием дефолтного определения.
     
  3. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    спасибо за заметку, вот я именно и ожидал ругани от компилера, и напоминается хелп с питона - лучше явное чем неявное)
    и кроме того в реализации С++ от MS немало палок, например экстерналы, покрытые безымянным неймспейсом таки экспортируются из объектных модулей, в отличии от тех же жсс и сланг. на самом деле косяков дохрена, чё говорить - если студия несмотря на явно установленный ключ /DEBUG линкует бинари с ключём /DEBUG:FASTLINK от чего потом ни виндбг ни ида символы не видят ..да индусы
    я тут же про баг с unified initialization описывал, и этих тонкостей дохуя)
     
    Последнее редактирование: 24 июл 2018
  4. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    а и сланг неймспейсы некорректно генерит по мс протоколу, потому шо индусы-от-мс написали компилер так что только им одним понятно
     
  5. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    sn0w, согласен с тобой, экстерналы в безымянном неймспейсе это плохо.
    Наверняка есть причина сделать именно так, вероятно был какой-то выбор наименьшего зла для разработчиков, все же MS компилирует добротный код.
     
  6. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    С виртуальными интерфейсами в C++ дела вообще обстояли трудно до появления умных указателей, разделение проекта на разные бинарные модули создавало неопределенность при разрушении объекта в чужом бинарном модуле в виду использования какого-то чужого (не родительского) деаллокатора памяти. Низкоуровневое наследие требует жертв ))
     
  7. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    sn0w, здесь, похоже, следующая логика.
    Так как конструктор короткий и его определение присутствует в теле класса, то компилер генерит тело в lazy-режиме: если конструктор где-то используется, то генерит код. Если не используется - то не генерит. У вас в коде нигде конструктор не вызывается, а потому генерить его нет смысла. А если нигде не создаётся инстанс объекта - то и таблица виртуальных функий нигде не используется.
    Во втором случае вы явно уже говорите компилятору, что надо генерить код, объявляя реализацию конструктора вне класса. Поэтому генерируется код конструктора, после чего мы и натыкаемся на проблему, что таблица виртуальных функций-то неполная, оказывается.
     
  8. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    господа, спасибо за ответы, в целом несколько разобрался. но, вообщем теже designated initializers вернут вроде как в цпп 20, странно что они их не заметили в 11, вообщем всем бобра)
     
  9. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    да это в курсе, как и про неявные конструкторы, которые инициализируют помимо vft нестатические мемберы с in-class definition, неявно добавляя конструктор. а вот в таких местах я бы таки добавил хотябы варнинг
     
  10. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    на сей раз прочитал вдумчиво. да и поэксперементировал с = delete; в целом в вопросе разобрался, спасибо за помощь.
     
  11. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    ну прикол в том что понятно что безымянные имена генерятся вроде как от имени, пути/ имени файла, по крайней мере это чтото статическое, не проверял. например манглинг неймспейса анонимного в анонимном попросту конкатит цифру вложенности(MSC), но, на выходе в объектных модулях эти имена PUBLIC, то есть видимы с других модулей. хотя в том же g++ нифига, static.