我有一个客户机-服务器应用程序。
客户端(TCP客户端)是一个Delphi应用程序,它向服务器发送命令(TCP服务器,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()正在抛出“创建变量或安全数组时出错”。
但在某些情况下,它是没有错误的。
有人知道吗?
最佳答案
基于Delphi10的源代码,问题来自于SafeArrayCreate
失败,很可能是由于OutofMemory异常。SafeArrayCreate
尝试分配160MB的内存,这需要是连续的。可能在进程的虚拟内存中没有足够大的“洞”来容纳这么多内存。在一个32位的进程中,我想这不太可能。
稍微缓解问题的一种方法可能是激活/largeaddressware标志。但这只会稍微降低发生错误的可能性,并可能在不久的将来再次出现。
其他选择包括:
编译为64位应用程序。
使用适当的数据库而不是内存中的数据集。