Сбой только при вызове сторонней DLL

Я должен использовать эту стороннюю DLL, которая взаимодействует с определенным оборудованием (оборудование, связанное с бразильским налоговым контролем).

Функции, представленные в этой библиотеке DLL, стандартизированы правительством и реализуются поставщиками оборудования. Наше программное обеспечение уже взаимодействует с несколькими библиотеками DLL поставщика, но с этим конкретным поставщиком все становится странно.

Что ж, я изолировал проблемный код, как вы можете видеть ниже:

...
function ConsultarSAT(numeroSessao : Longint ) : PAnsiChar ; stdcall; external 'sat.dll';
...

procedure TForm1.Button1Click(Sender: TObject);
begin
  ConsultarSAT(GetTickCount);
  ShowMessage('Will it crash?');
end;

Этот код вылетит, если встроен в конфигурацию выпуска, и не будет, если встроен в конфигурацию отладки. Сообщение ShowMessage было размещено, чтобы было ясно, что сбой произойдет в конце процедуры, а не во время вызова «ConsultarSAT».

Под аварией я подразумеваю:

Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 009E591C. Write of address 00000001'.

Поэтому я начал подозревать символы оптимизации и отладки. Затем я попробовал:

  • Конфигурация отладки с включенной оптимизацией: без сбоев
  • Конфигурация выпуска с отключенной оптимизацией: все еще сбой
  • Конфигурация отладки со всеми параметрами Compiler -> Debugging OFF: без сбоев
  • Конфигурация выпуска со всеми включенными параметрами компилятора -> отладки: все еще сбой

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

Я предполагаю, что проблема связана с каким-то беспорядком, созданным DLL в памяти, поэтому он работает нормально, но когда он возвращается, и мое приложение пытается получить доступ к некоторому пространству памяти, испорченному DLL, оно получает нарушение прав доступа.

Что еще я должен искать, чтобы узнать, что здесь происходит?


person Ricardo Acras    schedule 26.07.2018    source источник
comment
Комментарии не для расширенного обсуждения; этот разговор был перенесено в чат.   -  person    schedule 28.07.2018


Ответы (1)


Проблема заключалась в том, как я объявил функцию DLL. Я использовал stdcall, и DLL этого поставщика должна вызываться с помощью cdecl.

Разница между этими двумя способами вызова функции DLL, согласно этот пост касается только того, кто отвечает за очистку стека. Когда я использую stdcall, за очистку стека отвечает функция, а когда я использую cdecl, за это отвечает вызывающий.

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

person Community    schedule 02.08.2018
comment
Я не думаю, что это объясняет, почему происходит сбой только с конфигурацией выпуска. - person Sertac Akyuz; 02.08.2018