Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> vtables MSVC vs MinGW 
V
    Опции темы
borisbn
Дата 11.4.2012, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Здравствуйте.
Столкнулся с такой проблемой: есть dll-ка, созданная на MSVC 2008. В ней используется (как его обозвал xvr, кажется) недо-COM. Сейчас поясню. Описан виртуальный абстрактный интерфейс, сделан наследник от него и функция создания объекта
iface.h
Код

#pragma pack( push, 4 )
class IFace
{
protected:
    virtual ~IFace(){}
public:
    virtual void __stdcall init() = 0;
    virtual void __stdcall reset() = 0;
    virtual void __stdcall destroy() = 0;
};
#pragma pack( pop )     

iface_impl.h
Код

class IFaceImpl : public IFace
{
protected:
    virtual ~IFaceImpl() { OutputDebugStringA( __FUNCSIG__ ); }
public:
    virtual void __stdcall init() { OutputDebugStringA( __FUNCSIG__ ); }
    virtual void __stdcall reset() { OutputDebugStringA( __FUNCSIG__ ); }
    virtual void __stdcall destroy() {
        OutputDebugStringA( __FUNCSIG__ );
        delete this;
    }
};

ну и ф-ция создания объекта:
Код

extern "C" __declspec( dllexport ) IFace * __cdecl createIFace();
IFace * __cdecl createIFace() {
    return new IFaceImpl();
}

теперь в проекте на MinGW делаю следующее
Код

    typedef IFace * (__cdecl *PcreateIFace)();
    PcreateIFace createIFace;
    ... // получение через QLibrary::resolve функции "createIFace"
    if ( createIFace == 0 )
        return;
    IFace * iface = createIFace();
    iface->init();
    iface->reset();
    iface->destroy();

И вот тут начинаются чудеса. Вот вывод приложения
Цитата
void __stdcall IFaceImpl::reset(void)
void __stdcall IFaceImpl::destroy(void)
__thiscall IFaceImpl::~IFaceImpl(void)

а дальше приложение "падает". оно и понятно - вместо init() вызывается reset(), а вместо reset() - destroy()... дальше понятно, почему падает..

Немного поковырялся и нашёл, как вывести class layout в студии и в MinGW.
Вот студийный class layout
Цитата

1>class IFace size(4):
1> +---
1> 0 | {vfptr}
1> +---
1>IFace::$vftable@:
1> | &IFace_meta
1> |  0
1> 0 | &IFace::{dtor}                             <----------------------------------- обратите внимание
1> 1 | &IFace::init
1> 2 | &IFace::reset
1> 3 | &IFace::destroy
1>IFace::{dtor} this adjustor: 0
1>IFace::init this adjustor: 0
1>IFace::reset this adjustor: 0
1>IFace::destroy this adjustor: 0
1>IFace::__delDtor this adjustor: 0
1>IFace::__vecDelDtor this adjustor: 0               <---------- что это ???

вот MinGW-шный
Цитата

Vtable for IFace
IFace::_ZTV5IFace: 7u entries
0     (int (*)(...))0
4     (int (*)(...))(& _ZTI5IFace)
8     (int (*)(...))IFace::~IFace
12    (int (*)(...))IFace::~IFace                          <--------------- обратите внимание
16    (int (*)(...))__cxa_pure_virtual
20    (int (*)(...))__cxa_pure_virtual
24    (int (*)(...))__cxa_pure_virtual

Class IFace
   size=4 align=4
   base size=4 base align=4
IFace (0x7964f88) 0 nearly-empty
    vptr=((& IFace::_ZTV5IFace) + 8u)


Теперь, собственно, вопрос: откуда у MinGW взялся второй деструктор и что это за IFace::__vecDelDtor у студии ?
А, да... Самое главное: как, всё-таки их (студию и MinGW) подружить ?

Спасибо.

Это сообщение отредактировал(а) borisbn - 11.4.2012, 13:05


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 11.4.2012, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



подобную штуку я писал. но проверял как: gcc(.dll)-gcc(loader), mingw(.dll)-mingw(loader). все работает.

Добавлено через 32 секунды
Цитата(borisbn @  11.4.2012,  13:02 Найти цитируемый пост)
#pragma pack( push, 4 )

попробуй убери.
PM WWW   Вверх
borisbn
Дата 11.4.2012, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(boostcoder @  11.4.2012,  13:14 Найти цитируемый пост)
gcc(.dll)-gcc(loader), mingw(.dll)-mingw(loader). все работает

ну... среди "своих", понятно дело, разлада нету  smile 
проблема-то именно msvc(.dll)-mingw(loader)... я так понимаю, что и наоборот тоже будет проблема

Цитата(boostcoder @  11.4.2012,  13:14 Найти цитируемый пост)
попробуй убери. 

пробовал. так же пробовал от pack( 1 ) до pack( 8 ). Результат тот же.

Ты обратил внимание, что MinGW генерит 2 деструктора ? Откуда ?  smile 
Кстати, можешь сам попробовать - скомпилять этот h-ник с опцией -fdump-class-hierarchy
Будет создан файл имя_cpp_шника.class, из которого я и выдернул Dump из первого сообщения


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 11.4.2012, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  11.4.2012,  13:22 Найти цитируемый пост)
Ты обратил внимание, что MinGW генерит 2 деструктора ? Откуда ?

да. хз откуда.

венды под рукой нет, а gcc вообще не понимает что такое __stdcall  smile 
хотя, помоему, должен...

Добавлено через 6 минут и 17 секунд
http://liveworkspace.org/code/c08712cda514...6ffd45d6b63fb95

PM WWW   Вверх
borisbn
Дата 11.4.2012, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(boostcoder @  11.4.2012,  13:34 Найти цитируемый пост)
gcc вообще не понимает что такое __stdcall

MinGW понимает. И правильно понимает.
Хмммм.... Если верить студийному дампу
Цитата
1>IFace::__delDtor this adjustor: 0
1>IFace::__vecDelDtor this adjustor: 0

то у студийного интерфейса тоже 2 деструктора: обычный IFace::__delDtor и какой-то "векторный" что-ли - IFace::__vecDelDtor
может у gcc/mingw 2-й деструктор тоже "векторный", но располагается в виртуальной таблице сразу за обычным, а в студии в конце, например ?
Пойду погуглю про vecDelDtor


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Dem_max
Дата 11.4.2012, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



а обязательно из DLL возвращать IFace ???? может сделать проще, IFace пускай будет внутри DLL  а из нее только экспортировать обычные функции работающие с IFace


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
borisbn
Дата 11.4.2012, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Dem_max, да оно-то можно... но хотелось бы более ... высокоуровнево что-ли работать.
И ещё: сейчас я подгружаю dll-ку динамически (QLibrary::resolve). При большом количестве функций в интерфейсе это будет напрягать.
Сейчас при изменении интерфейса мне достаточно перекомпилировать оба проекта и всё. А так - ещё не забыть добавить соответствующую функцию в таблицу экспорта... Неохота... А главное - обидно - у меня такая связка работает на куче проектов на Builder'е, студийном и интеловском компиляторах...

P.S. Подгружать dll-ку статически (через библиотеку импорта) не могу, т.к. по логике работы при отсутствии dll-ки у меня работает один код, а при наличие - код из неё.
Да и просто интересно уже разобраться как подружить детей Била Гейтса и boostcoder'а  smile  smile  smile 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 11.4.2012, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



он ведь так и сделал:
Цитата

IFace * __cdecl createIFace() {
    return new IFaceImpl();
}

PM WWW   Вверх
borisbn
Дата 11.4.2012, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



boostcoder, не... насколько я понял, Dem_max имел в виду что-то типа такого
Код

extern "C" __declspec( dllexport ) void IFace_init( IFace * p );
extern "C" __declspec( dllexport ) void IFace_reset( IFace * p );
extern "C" __declspec( dllexport ) void IFace_destroy( IFace * p );

void IFace_init( IFace * p ) {
    p->init();
}
void IFace_reset( IFace * p ) {
    p->reset();
}

void IFace_destroy( IFace * p ) {
    p_destroy();
}



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 11.4.2012, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



borisbn, так этого не нужно. то что ты сделал должно работать.

PM WWW   Вверх
borisbn
Дата 11.4.2012, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(boostcoder @  11.4.2012,  15:49 Найти цитируемый пост)
то что ты сделал должно работать

однако, при таком вызове
Цитата(borisbn @  11.4.2012,  13:02 Найти цитируемый пост)
    iface->init();
    iface->reset();
    iface->destroy();

вызывается так
Цитата(borisbn @  11.4.2012,  13:02 Найти цитируемый пост)
void __stdcall IFaceImpl::reset(void)
void __stdcall IFaceImpl::destroy(void)

и очень похоже, что из-за второго деструктора.

Цитата(borisbn @  11.4.2012,  13:41 Найти цитируемый пост)
может у gcc/mingw 2-й деструктор тоже "векторный", но располагается в виртуальной таблице сразу за обычным, а в студии в конце, например ?
Пойду погуглю про vecDelDtor

очень похоже на правду... вот здесь - http://www.developerfusion.com/article/843...th-the-dia-sdk/ - в разделе "Running the utility" есть такой код с примечательными комментариями
Цитата

struct base
    {
  char char_by_value;
    private:
  int a;
    public:
  virtual /*dtor*/ base::~base();
  /*ctor*/ base::base();
  // void __local_vftable_ctor_closure();
  // virtual void* __vecDelDtor(unsigned int);
    };



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
sergioK1
Дата 12.4.2012, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(borisbn @ 11.4.2012,  14:24)
Да и просто интересно уже разобраться как подружить детей Била Гейтса и boostcoder'а  smile  smile  smile

Да никак, хотя  может дэ фукс и получиться чего
Не пользуй под винду не родное и спи спокойно  smile 
И доку читай Мелкософта , там это написано ,


 
PM MAIL   Вверх
borisbn
Дата 12.4.2012, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



sergioK1, если хочешь потроллить - ошибся адресом. Я не кормлю троллей.
Если хочешь помочь в проблеме - расскажи, что ты вычитал в "доке у Майкрософта". А ещё лучше дай ссылку, а то твои выражения непросто понять.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alexeis
Дата 12.4.2012, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



borisbn, COM интерфейс ничего не знает о деструкторах. Деструкторы это непереносимая фишка С++. Виртуальный деструктор может быть в классе, но его не должно быть в COM интерфейсе. Поскольку ты использовал непереносимую конструкцию вот и поимел проблемы.   
  Для уничтожения объекта можешь написать простые виртуальные функции. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
sergioK1
Дата 12.4.2012, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(borisbn @ 12.4.2012,  11:33)
sergioK1, если хочешь потроллить - ошибся адресом. Я не кормлю троллей.
Если хочешь помочь в проблеме - расскажи, что ты вычитал в "доке у Майкрософта". А ещё лучше дай ссылку, а то твои выражения непросто понять.

Попробуй в "обычном" эклипсе (http://www.eclipse.org/downloads/) в худшем случае полчаса потеряешь, 
просто попробуй,  2 строку  выбери,   Я не понимаю "что-такое mingw" 

доке у Майкрософта явно "про детей" ничего не сказано, неявно между строк да,
 плюс у меня чутье с опытом наработанное, нюх что ли как у собаки  smile  
 не пользуй - будут проблемы,  KISS.

Если под VC работает то что еще надо-то?, твой product manager этого не понимает ?,
для кастомера какая разница ? 
или Я чего не понимаю .





 
PM MAIL   Вверх
boostcoder
Дата 12.4.2012, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



оно и под мингв работает, если ты вдруг не заметил ;)

PM WWW   Вверх
xvr
Дата 12.4.2012, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(borisbn @  11.4.2012,  13:02 Найти цитируемый пост)
1> | &IFace_meta
1> |  0

и
Цитата(borisbn @  11.4.2012,  13:02 Найти цитируемый пост)
0     (int (*)(...))0
4     (int (*)(...))(& _ZTI5IFace)

- поддержка RTTI (и Exception'ов)

Цитата(borisbn @  11.4.2012,  13:02 Найти цитируемый пост)
1>IFace::{dtor} this adjustor: 0
1>IFace::init this adjustor: 0
1>IFace::reset this adjustor: 0
1>IFace::destroy this adjustor: 0
Поддержка множественного наследования (в этих слотах лежат смещения от this, переданного в метод родителя, до реального this потомка)
Цитата

1>IFace::__delDtor this adjustor: 0
1>IFace::__vecDelDtor this adjustor: 0
Смещения this'ов для operator delete и operator delete[] для класса (IMHO)


Это сообщение отредактировал(а) xvr - 12.4.2012, 14:07
PM MAIL   Вверх
boostcoder
Дата 12.4.2012, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



xvr, и? какой вывод? какое решение?
PM WWW   Вверх
borisbn
Дата 12.4.2012, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(sergioK1 @  12.4.2012,  13:37 Найти цитируемый пост)
Если под VC работает то что еще надо-то?

я тебе уже отвечал на это

Цитата(xvr @  12.4.2012,  14:07 Найти цитируемый пост)
поддержка RTTI

Я тоже так подумал сначала. Для чего отключил поддержку RTTI в студии и перекомпилял. Вывод class layout'а нисколько не изменился...

Цитата(xvr @  12.4.2012,  14:07 Найти цитируемый пост)
Смещения this'ов для operator delete и operator delete[] для класса

да, похоже. причём студия второй деструктор не вставляет в vtable (или вставляет в конце), а мингв - вставляет сразу после первого...

Цитата(Alexeis @  12.4.2012,  12:49 Найти цитируемый пост)
 Для уничтожения объекта можешь написать простые виртуальные функции.  

так и сделал (IFace::destroy())... я просто хотел защититься от удаления указателя на интерфейс из exe-шника, поэтому и сделал protected-деструктор.
Скорее всего, Alexeis, ты прав, и нужно будет просто выкинуть этот деструктор.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
xvr
Дата 12.4.2012, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @ 12.4.2012,  14:09)
xvr, и? какой вывод? какое решение?

Ну собственно Alexis уже предложил решение - не использовать деструктор. Ну и поискать опции, что бы убрать поддержку множественного наследования из таблицы. (/vd0 и возможно еще что то, надо искать)


PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1596 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.