我必须使用与特定硬件(与巴西税控相关的硬件)进行通信的第三方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'.
所以我开始怀疑优化和调试符号。然后我尝试了:
如果我运行上面的代码,该代码仅从函数中获取返回值并将其显示在showMessage上,则我仍然遇到相同的崩溃情况,但是我能够验证该函数返回了正确的值。
我想这个问题与内存中DLL造成的某种混乱有关,因此它可以正常运行,但是当它返回并且我的应用尝试访问DLL所困扰的某些内存空间时,就会出现访问冲突。 / p>
我还应该寻找什么来了解这里发生的情况?
答案 0 :(得分:0)
问题是我声明DLL函数的方式。我使用的是stdcall,必须使用cdecl调用此供应商的DLL。
根据this post,这两种调用DLL函数的方式之间的区别仅在于谁负责清理堆栈。当我使用stdcall时,函数的责任是清理堆栈,而当我使用cdecl时,则是调用者的责任。
我对此的知识非常有限,但是我想这种行为可以解释我在这里遇到的所有奇怪问题。问题本身已经解决并经过了深入的测试,但是如果有一个比我更深入的知识的人可以更深入地解答问题,那么其他有类似问题的人可以比我深入研究这个问题的时间更少。