2016-11-16 7 views
0

после прочтения и обучения в течение многих лет на этой великолепной платформе теперь мой первый пост.Соглашения о вызове DLL и нарушение прав доступа

Моя проблема:

В C++ Я пытаюсь создать динамическую библиотеку (32 бит), который будет служить в качестве клиента AQMP связи (на основе SimpleAmqpClient). Затем файл dll будет использоваться внутри стороннего приложения (32 бит).

Во время моих тестов, когда я вызываю DLL в пользовательский исполняемый файл, все работает нормально. Но когда я пытаюсь использовать dll в стороннем приложении, я получаю ошибку нарушения доступа (0x00000000). Я узнал, что проблема может быть вызовом вызова функции.

С помощью нескольких строк кода, представленных ниже, эта ошибка может быть воспроизведена. Он исчезает, если я удаляю выражение __stdcall в mytest.dll. Обычно я ожидаю, что код будет работать, потому что он использует одно и то же соглашение о вызовах в custom_test.exe и mytest.dll. (Sidenote: стороннее приложение ожидает функцию __stdcall, поэтому я полагаюсь на это)

Я хотел бы понять это поведение. Заранее спасибо!

Мои настройки:

  • ОС: Windows 7
  • 32 бит Компилятор: GCC 5.3 (Cygwin)

Мой код (custom_test.exe):

#include <stdio.h> 
#include <windows.h> 


int main(void) { 

    HINSTANCE hInstance;  
    hInstance=LoadLibrary("mytest.dll"); 
    FARPROC lpfnGetProcessID = GetProcAddress(HMODULE(hInstance), "test"); 

    // Function prototype 
    typedef void (__stdcall *myFunction)(void); 
    myFunction test; 
    test = myFunction(lpfnGetProcessID); 

    // Call Function 
    test(); 

    FreeLibrary(hInstance); 
} 

Мой код (mytest.dll):

extern "C" __declspec(dllexport) void __stdcall test(void) { 

    printf("Inside Function \n"); 
} 

компилировать код с помощью

  • дллы: g++ mytest.cpp -o mytest.dll -shared -std=gnu++11
  • ех: g++ custom_test.cpp -o custom_test.exe -std=gnu++11

ответ

0

__stdcall конвенция делает его ответственностью вызываемой функции, чтобы очистить стек при возврате, в то время как __cdecl делает его ответственностью.

Мы не можем видеть фактическое объявление в сторонней DLL, но мое первоначальное предположение состояло в том, что DLL ожидает аргументы и использует либо то, что, по его мнению, является аргументом стека по ошибке, либо очищает стек основанный на его предположении о аргументах стека и, как правило, возиться со стеком.

EDIT В этом случае, хотя я вижу, что при компиляции в 32 бита, тестовая функция экспортируется с именем «тест @ 0». Если вы измените свой GetProcAddress, чтобы использовать это украшенное имя, оно будет работать.

+0

Thx для вашего ответа! В моем первом посте я просто хотел показать большую картину моей задачи. Ошибка может быть воспроизведена только с заданным кодом и без каких-либо дополнительных зависимостей (сторонняя библиотека или приложение). – wolfspex

+0

Обновлен ответ - см. EDIT –

0

Хорошо, теперь через несколько часов я снова вижу четкость! Thx IanM_Matrix1 для предложения, так называемое украшение имен действительно было точкой.

После моего исследования я могу теперь поделиться некоторыми полезными RESSOURCES я нашел: Важно знать, что некоторые компиляторы добавить различные украшения, чтобы имена функций, смотрите здесь: http://wyw.dcweb.cn/stdcall.htm

Имея это в виду, можно прочитать эту страницу о соглашениях о вызовах Win32 в целом: http://www.unixwiz.net/techtips/win32-callconv.html

При использовании gcc украшения можно также отключить с помощью флага -Wl,--kill-at.