“在Delphi中的TClientDataSet.LoadFromStream()中创建变量或安全数组时出错”

时间:2017-01-12 15:19:21

标签: c++ database delphi tcp c++builder

我有一个客户端 - 服务器应用程序。 客户端(TCP Client)是一个Delphi应用程序,它向服务器发送命令(TCP Server,C ++ Builder应用程序) 它们都是用 Rad Studio XE2 编写的 服务器响应命令从SQL Server获取数据并将其发送到客户端 服务器使用 TClientDataSet 并将其保存到发送给客户端的 TMemoryStream 。 客户端还使用 TClientDataSet 并对从服务器接收的流调用 TClientDataSet.LoadFromStream()
这很有效。
但是有一种情况是数据大小较大(约160 MB),其中有时“创建变量或安全数组时出错”在调用 TClientDataSet.LoadFromStream()在客户端。

服务器以这种方式将流发送到客户端:

//...
FContext->Connection->IOHandler->LargeStream = true;
FContext->Connection->IOHandler->Write(Stream, 0, true);

客户端以这种方式接收它:

AClient.IOHandler.LargeStream := True;
AClient.IOHandler.ReadStream(Stream, -1, False);

客户端收到后,会将流的位置更改为18 因为实际数据在18个字节后开始。然后它调用 TClientDataSet.LoadFromStream()

//...
MemTable.LoadFromStream(Stream);

LoadFromStream()正在抛出“创建变体或安全数组的错误”。 但有些情况下它没有错误地工作。

有没有人有任何想法?

1 个答案:

答案 0 :(得分:0)

基于Delphi 10的源代码,问题来自SafeArrayCreate失败,很可能是因为EOutOfMemory异常。

SafeArrayCreate尝试分配160MB的内存,这需要是连续的。你的进程的虚拟内存中可能没有足够大的“漏洞”来适应那么多的内存。在一个32位的过程中,我猜这不太可能。

缓解问题的一种方法可能是激活/ LARGEADDRESSAWARE标志。但这只会略微减少错误发生的可能性,并可能在未来很快再次出现。

其他选项包括:

  • 编译为64位应用程序。

  • 使用适当的数据库而不是内存数据集。