Очень странное поведение MinGW

Тема в разделе "LANGS.C", создана пользователем macrouser, 19 авг 2010.

  1. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    добрый день всем! появилась такая проблема, даже не знаю, отчего:

    имеется проект в CodeBlocks, target - Release, доп. опции линкера: -nostdlib, подключена одна либа: libkernel32.lib. в проекте два файла: main.cpp и api.h.

    содержимое main.cpp

    Код (Text):
    1. #include <windows.h>
    2. #include "api.h"
    3.  
    4. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    5.  
    6.     _MessageBox(0, "2", "", 0);
    7.  
    8.     return 0;
    9. }
    содержимое api.h

    Код (Text):
    1. int (WINAPI *_MessageBox) (HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
    2.  
    3. void LoadAPI(void) {
    4.  
    5.     HMODULE user32_dll   = LoadLibrary("user32.dll");
    6.     *(FARPROC*)&_MessageBox = GetProcAddress(user32_dll, "MessageBoxA");
    7.  
    8.     _MessageBox(0, "1", "", 0);
    9.  
    10. }
    LoadAPI НЕ вызывается из WinMain, тоесть функция _MessageBox не получает адреса... все это компилируем, и после запуска какой вылетит мессадж бокс? по сути - никакой вылететь не должен - приложение должно упасть.. но вылетает мессаджбокс с текстом 1 ! как так, если я эту функцию вобще не вызываю? более того, если и вызываю, то выполняется только она, как будто она и является точкой входа... отчего такое может быть?

    спасибо!
     
  2. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    macrouser
    Попробуй для эксперимента поместить ф-цию LoadAPI в main.cpp, после ф-ции WinMain.

    Если не используешь CRT, нужно явно указать линкеру entry point (в ld это опция -e, по-моему).
     
  3. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    Checking for existence: C:\Users\admin\Documents\My Projects\test\bin\Release\test.exe
    Executing: "C:\Users\admin\Documents\My Projects\test\bin\Release\test.exe" (in C:\Users\admin\Documents\My Projects\test\.)
    Process terminated with status -1073741819 (0 minutes, 4 seconds)

    ну это очевидно, теперь, видимо, первой исполняется WinMain, но функция _MessageBox не имеет адреса, соответственно приложение крешится... кстати, вот еще забыл что сказать:

    стоит в настройках компилятора убрать опцию -nostdlib, как все вдруг работает как нужно, вызывается в нужном порядке... но мне не нужны дефольтные либы, в таблице импорта появляется сразу msvcrt с несколькими функциями...
     
  4. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    -e - адрес входа.. но как мне его узнать?

    UPD: попробывал добавить --start=WinMain - тоже не помогает...
     
  5. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    macrouser
    Нужно использовать манглированное имя: _WinMain@16
     
  6. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    а как мне его узнать, если у меня EP самописная? например:

    Код (Text):
    1. void Trololo(void) {
    2.  
    3. //--
    4.  
    5. }
     
  7. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    macrouser
    Манглированное имя как узнать?
    C-ф-ции GCC манглит так:
    _<имя> для __cdecl-ф-ции
    _<имя>@<суммарный размер аргументов в байтах> для __stdcall-ф-ции.

    т.е. WinMain манглится как _WinMain@16, а Trololo - как _Trololo

    Для C++-ф-ций точного алгоритма манглирования не знаю, но манглированное имя можно узнать, посмотрев в asm-листинг.
    --
    Кстати, если используешь свою EP, то она должна иметь тип int (void);
    Т.е. без аргументов.
     
  8. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    http://en.wikipedia.org/wiki/Name_mangling
     
  9. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    так-с, с WinMain работает -e_WinMain@16 с трололо -e_Trololo не хочет (: но уже хоть что-то.... спасибо большое!
     
  10. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    n0name
    спасибо за линк, попробывал подобрать по нему, но неполучилось... -e_Z1Trololov, -eTrololo__v, -e_Trololo__v не прокатывают...
     
  11. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    macrouser
    Код (Text):
    1. extern "C"
    2. void Trololo(void) {
    3.  
    4. //--
    5.  
    6. }
     
  12. macrouser

    macrouser New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2010
    Сообщения:
    16
    большое спасибо, оно работает!