странности компилятора С++

Тема в разделе "LANGS.C", создана пользователем GoldFinch, 23 ноя 2008.

  1. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    исходный код:
    Код (Text):
    1.     class UNetworkHandler;
    2.     typedef User* (UNetworkHandler::*T_GetUser)(int a1);
    3. ...
    4.     __declspec(dllexport) UNetworkHandler *g_NetworkHandler;
    5.     __declspec(dllexport) T_GetUser GetUser;
    6. ...
    7.     __debugbreak();    
    8.     User *U = (g_NetworkHandler->*GetUser)(g_UserID);
    9.     __debugbreak();
    результат:
    Код (Text):
    1. .text:1000127B                 int     3               ; Trap to Debugger
    2. .text:1000127C                 mov     ecx, dword_10013B84
    3. .text:10001282                 test    ecx, ecx
    4. .text:10001284                 jnz     short loc_10001295
    5. .text:10001286                 mov     eax, UNetworkHandler * g_NetworkHandler
    6. .text:1000128B                 mov     ecx, dword_10013B7C
    7. .text:10001291                 add     ecx, eax
    8. .text:10001293                 jmp     short loc_100012B0
    9. .text:10001295 ; ---------------------------------------------------------------------------
    10. .text:10001295
    11. .text:10001295 loc_10001295:                           ; CODE XREF: sub_10001270+14j
    12. .text:10001295                 mov     eax, dword_10013B80
    13. .text:1000129A                 mov     edx, UNetworkHandler * g_NetworkHandler
    14. .text:100012A0                 mov     esi, [eax+edx]
    15. .text:100012A3                 mov     ecx, [esi+ecx]
    16. .text:100012A6                 add     ecx, eax
    17. .text:100012A8                 add     ecx, dword_10013B7C
    18. .text:100012AE                 add     ecx, edx
    19. .text:100012B0
    20. .text:100012B0 loc_100012B0:                           ; CODE XREF: sub_10001270+23j
    21. .text:100012B0                 mov     edx, ulong g_UserID
    22. .text:100012B6                 push    edx
    23. .text:100012B7                 call    User * (UNetworkHandler::*GetUser)(int)
    24. .text:100012BD                 int     3               ; Trap to Debugger
    чтоета???

    ЗЫ: msvc2008, настройки - релиз
     
  2. Ursus

    Ursus Member

    Публикаций:
    0
    Регистрация:
    15 мар 2006
    Сообщения:
    238
    Адрес:
    Russia
    Какое слово непонятно???
     
  3. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    мне непонятно почему вместо
    int3
    push ulong g_UserID
    mov ecx, UNetworkHandler * g_NetworkHandler
    call User * (UNetworkHandler::*GetUser)(int)
    int3

    получилась эта хрень

    я обфускацию не заказывал =\
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    может тебе оптимизацию включить? О1 О2 Ох и т.д.
     
  5. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    GoldFinch
    Выключи RTTI (C++ > Language > Enable RTTI = No).
     
  6. Ursus

    Ursus Member

    Публикаций:
    0
    Регистрация:
    15 мар 2006
    Сообщения:
    238
    Адрес:
    Russia
    причем тут RTTI и оптимизация? По мне, там обычный вызов виртуальной функции через vtable.
     
  7. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    cresta
    оптимизация включена - /Ox /Ob1 /O

    green
    RTTI отключил, непомогло

    Ursus
    там вызов по указателю
    call User * (UNetworkHandler::*GetUser)(int)
    т.е. call dword ptr [GetUser]
     
  8. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    наверное С++ хороший язык.. если не смотреть что за гуан он компилит =\
     
  9. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    У класса есть множественное виртуальное наследование?
     
  10. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    reverser
    описание класса в 1м посте

    могу добавить тольк строчку
    (FARPROC &)GetUser=GetProcAddress((HMODULE)g_hEngine,UNETWORKHANDLER_GETUSER);
     
  11. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Это особенности работы с pointer-to-member в C++. В данном конкретном случае sizeof(T_GetUser) = 16, а вовсе не 4, как у обычных указателей. Все эти действия действительно нужны для определённых ситуаций для получения корректного указателя this. В данном случае компилятору неизвестно ничего ни о классе UNetworkHandler, ни о указателе GetUser, так что он должен рассматривать разные извращённые ситуации, простейшую из которых демонстрирует пример
    Код (Text):
    1. class UNetworkHandler
    2. {
    3. public:
    4. User* fn1(int a1);
    5. };
    6. class Derived : public UNetworkHandler
    7. {
    8. public:
    9. User* fn2(int a1);
    10. virtual void somefunction(void);
    11. }
    12. T_GetUser GetUser1 = &UNetworkHandler::fn1;
    13. T_GetUser GetUser2 = static_cast<T_GetUser>&Derived::fn2;
    14. ...
    15. g_NetworkHandler = new Derived;
    16. ...
    (предлагаю помедитировать над вопросом, где в g_NetworkHandler находятся элементы класса UNetworkHandler и что нужно делать с указателем this класса Derived, чтобы он стал указателем this класса UNetworkHandler).
     
  12. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    diamond
    и как сделать чтобы компилился нормальный код?

    push [g_UserID]
    mov ecx, [g_NetworkHandler]
    call [GetUser]
     
  13. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Так ведь проблема в том, что код
    Код (Text):
    1. push [g_UserID]
    2. mov ecx, [g_NetworkHandler]
    3. call [GetUser]
    может быть просто неверен - this для функции [GetUser] может не совпадать с [g_NetworkHandler].

    Но если очень хочется, то можно:
    Код (Text):
    1. class __single_inheritance UNetworkHandler;
     
  14. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    diamond
    "class __single_inheritance UNetworkHandler;"
    спасибо, помогло.


    я пытаюсь перенести рабочий код с фасма на С++, и хочу чтобы откомпиленный код С++ был не хуже исходного. пока удается с трудом =\