Delphi - 在连接到 Oracle 并调用 Web 服务方法后关闭时 ntdll.dll 中的异常

Posted

技术标签:

【中文标题】Delphi - 在连接到 Oracle 并调用 Web 服务方法后关闭时 ntdll.dll 中的异常【英文标题】:Delphi - Exception in ntdll.dll on closing after both connection to Oracle and calling a web service method 【发布时间】:2012-10-17 22:14:16 【问题描述】:

在 Delphi 2009 中,我发现每当我执行 both 到 Oracle 的连接(通过 OCI.dll)和对 Web 服务方法的调用时,我都会在 ntdll.dll 中遇到异常在 IDE 中关闭我的应用程序时。

对于与 Oracle 的连接,我尝试使用 DOA(直接 Oracle 访问)4.1.1.0 和 ODAC 组件(最新试用版);

对于 Web 服务方法调用(只是一个简单的“函数 HelloWorld:字符串”),在从 Web 服务导入 WSDL 之后,我正在使用 Delphi 的库存功能。

如果我在“直接”模式下使用 ODAC 组件,即不使用 OCI.dll,则关闭时不会出现异常。

如果我只调用 Web 服务方法(不连接到 Oracle),则关闭时不会发生异常(即使我使用 DOA 或 ODAC 组件)。

如果我只连接到 Oracle(通过 OCI.dll)(不调用 Web 服务方法),一切都会正常(无论我使用 DOA 还是 ODAC 组件)。

同样的代码在 Delphi 7 和 Delphi XE2 中都可以完美运行:应用程序关闭时不会出现异常。

一些信息: Delphi 2009(股票和更新 3 版本) 操作系统:Windows 7 32 位 Oracle Instant Client 10.2.0.4 和 Oracle Instant Client 10.2.0.5

我开始怀疑这可能与 Delphi 2009 中应用程序关闭时的堆损坏有关...

有什么帮助吗?

复制步骤(来自评论):

    创建新的 VCL 表单应用程序 在表单上放置一个 TOracleSession DOA 组件(名为 OracleSession1) 在窗体上放置一个 TButton(名为 Button1) 为按钮单击事件放置此事件处理程序:

代码如下:

procedure TForm1.Button1Click(Sender: TObject);
var
   MyWebService3Soap: WebService3Soap;
   s: string;
begin
   OracleSession1.LogonDatabase := 'SomeLogonDB';
   OracleSession1.LogonUsername := 'SomeUsername';
   OracleSession1.LogonPassword := 'SomePassword';
   OracleSession1.Connected := True;
   ShowMessage('Connected');

   MyWebService3Soap := GetWebService3Soap();
   s := MyWebService3Soap.HelloWorld(); // Just returns a string such as "Hello World"
   ShowMessage(s);
 end;

“WebService3Soap”接口是 Delphi 2009 WSDL Importer 自动生成的接口。这是有意义的部分:

WebService3Soap = interface(IInvokable)
  ['F6F12FA6-3881-8BB5-AD71-2408B47692CD']
    function  HelloWorld: string; stdcall;
  end;

function GetWebService3Soap(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): WebService3Soap;

initialization
  InvRegistry.RegisterInterface(TypeInfo(WebService3Soap), 'http://mytest.it/Test3', 'utf-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(WebService3Soap), 'http://mytest.it/Test3/HelloWorld');
  InvRegistry.RegisterInvokeOptions(TypeInfo(WebService3Soap), ioDocument);
end.

在 IDE 中运行应用程序,按下按钮(关闭后面的 2 个 ShowMessages),然后关闭表单。

【问题讨论】:

没有任何代码或任何重现方式都无法解释。请给我们一些可以合作的东西。 我会在完全调试模式下使用 FastMM 来获取有关内存损坏的一些信息。此外,madExcept 等工具可以为您提供有用的堆栈跟踪。 不是一个解决方案,但您可以尝试: 1) 不同的初始化顺序 - 首先是 OCI,然后是 WebServ,然后是向后。 2) 通过包围 WSAStartup / WSACleanup 的 OCI 和 WebServ 调用来显式控制 Winsock。 3) 这可能是一个“DLL 地狱”问题 - 查看仅由 OCI 和仅由 WebServ 加载的 DLL。 【参考方案1】:

鉴于这可能是“DLL 地狱”问题,我能够在 Windows XP 和 Vista 上运行测试:一切正常。所以我开始认为这个问题一定与 Windows 7 上的 Delphi 2009 有关。

我是对的,我发现 Delphi 2009 在 Windows 7 上调试存在问题。

幸好有补丁可用:

ID: 27476, Hotfix 2 for Delphi 2009 and C++Builder 2009

应用补丁解决了!

【讨论】:

以上是关于Delphi - 在连接到 Oracle 并调用 Web 服务方法后关闭时 ntdll.dll 中的异常的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Delphi 调用 Oracle 函数?

如何在连接到远程系统的设备上部署和执行应用程序?

delphi如何连接oracle数据库

DBGrid 中的 Delphi 2010 计算列

无法在连接到石墨的 grafana 上创建图表

Node 在连接到 Postgres 方面比 .NET Core 快 20 倍