странное повреждение стека из-за вызова DLL - PullRequest
0 голосов
/ 14 июля 2010

Я пытаюсь вызвать функцию DLL (через GetProcAddress и т. Д.) Из C, используя компилятор lcc.Функция вызывается, и все идет хорошо, но похоже, что вершина стека повреждена.Я пытался поиграть с соглашениями о вызовах (__stdcall / __cdecl), но это не помогло.

К сожалению, у меня нет доступа к коду dll, и мне приходится использовать компилятор lcc.

Я обнаружил, что этот простой хак позволяет избежать повреждения стека:

void foo(params)
{
  int dummy;
  dll_foo(params);
}

Здесь dll_foo - указатель, возвращаемый GetProcAddress, а стек как бы защищен фиктивной переменной.Таким образом, поврежден не указатель стека, а данные в верхней части стека.Это работает следующим образом, но я хотел бы знать причину повреждения.

Есть идеи?

UPD: Как уже было сказано в комментариях, вот фактические типы функций:

typedef unsigned char (CALLBACK Tfr)(unsigned char);
typedef void (CALLBACK Tfw)(unsigned char,unsigned char);
typedef int (CALLBACK Tfs)(int);
typedef void (CALLBACK Tfwf)(int*,int);

Все они показывают похожее поведение.

К сожалению, присоединить отладчик не так просто, так как код компилируется и запускается Matlab с использованием компилятора LCC, и естьнет поддержки отладки.Возможно, мне придется воспроизвести эту проблему в автономной конфигурации, но это не так просто сделать.

Ответы [ 3 ]

2 голосов
/ 14 июля 2010

Похоже, вы используете MSVC, Debug + Windows + регистры. Посмотрите на значение ESP до и после звонка. Если он не совпадает, то сначала измените соглашение о вызовах в объявлении указателя функции (правильно ли вы это сделали?) Если он все еще не совпадает, то это __stdcall, и вы не угадали аргументы, которые нужно правильно передать.

Или функция могла бы просто забить кадр стека, это не невозможно.

Публикация объявления указателя функции, которое показывает real аргументы, вероятно, поможет диагностировать это лучше.

1 голос
/ 14 июля 2010

Вы можете попытаться «следовать» вызову dll_foo () i на ассемблере с помощью отладчика, чтобы проверить, что именно выполняет подпрограмма в стеке.

1 голос
/ 14 июля 2010

Мне кажется, что вы на правильном пути, глядя на соглашение о вызовах.Главное, что вам нужно сделать, это убедиться, что вызывающий и вызываемый абоненты используют одно и то же соглашение.Обычно для DLL вы хотите использовать __stdcall для обоих, но если (как вы говорите) у вас нет контроля над DLL, то вам нужно изменить свой код, чтобы он соответствовал тому, что он делает.К сожалению, почти невозможно угадать, что это такое - я почти уверен, что lcc (как и большинство компиляторов C и C ++) может создавать код для использования с различными соглашениями.лишнее слово в стеке, похоже, у вас в настоящее время есть несоответствие, когда и вызывающий, и вызываемый абонент пытаются удалить аргументы из стека (например, вызывающий абонент использует __cdecl и вызываемый использует __stdcall.

...