导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2018/12/3 16:15:12
标题:
TmemoryStream释放出错
浏览:1616
加入我的收藏
楼主:
Datasnap服务器上定义一个函数,返回类型是Tstream,如下 function TDSClient.GetDemo : TStream; var stream: TMemoryStream; LQry: TFDQuery; Sa: TFDSchemaAdapter; begin try Sa := TFDSchemaAdapter.Create(nil); LQry := TFDQuery.Create(nil); try with LQry do begin SchemaAdapter := Sa; Connection := dm.GetSYSConnection; SQL.Text := 'SELECT * FROM DEMO'; Open; end; stream := TMemoryStream.Create; Sa.SaveToStream(stream, sfBinary); stream.Position := 0; Result := stream; except on e: Exception do begin raise ; end; end; finally FreeAndNil(LQry); FreeAndNil(Sa); end; end; 在客户端这边 定义一个函数,调用服务器方法,如下 var DS: TDSClient; tbl: TFDMemTable; stream: TStream; begin try tbl := TFDMemTable.Create(nil); stream := TMemoryStream.Create; DS := TDSClient.Create(con.DBXConnection); stream := DS.GetDemo //服务器上定义的函数 finally FreeAndNil(tbl); FreeAndNil(DS); stream.free //这里出错,提示无效的指针操作 end; end; 请教各位,这问题是什么原因
----------------------------------------------
-把学习当信仰
作者:
2018/12/3 16:49:35
1楼:
stream := DS.GetDemo 感觉这样不对吧?
----------------------------------------------
-delphi新资讯站 http://www.delphigear.cn
作者:
vga (vga)
★☆☆☆☆
-
盒子活跃会员
2018/12/3 17:22:16
2楼:
stream := TMemoryStream.Create; // 这里分配了一个 stream := DS.GetDemo //服务器上定义的函数 // 这里指向另外的地方
----------------------------------------------
-
作者:
2018/12/3 17:48:23
3楼:
2楼已经指出了问题的关键,改成这样就可以了: var DS: TDSClient; tbl: TFDMemTable; stream: TStream; begin stream:= nil; try tbl := TFDMemTable.Create(nil); DS := TDSClient.Create(con.DBXConnection); stream := DS.GetDemo //服务器上定义的函数 finally FreeAndNil(tbl); FreeAndNil(DS); if assigned(stream) then FreeAndNil(stream); end; end;
----------------------------------------------
虽千万人吾往矣!
作者:
2018/12/3 21:30:06
4楼:
还是一样的提示 无效指针操作
----------------------------------------------
-把学习当信仰
作者:
2018/12/3 22:22:25
5楼:
用json,别用TStream
----------------------------------------------
-
作者:
2018/12/3 23:37:03
6楼:
暂时不考虑用json
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 12:19:23
7楼:
估计是TDSClient自己释放了stream,你查看一下源代码。
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
2018/12/4 14:24:33
8楼:
这样返回TSTREAM问题多多吧吗? 建议你改下返回方式: function TDSClient.GetDemo(var sResult: TStream):Boolean; begin Result := False; if not Assigend(sResult) then Exit; ...... ...... Result := True; end; 调用的时候,客户端: stream := TMemoryStream.Create; if DS.GetDemo(stream ) then begin ....... ....... end else MsgBox...or Reture Msg; if Assigned(stream) then FreeAndNil(stream);
----------------------------------------------
简单做人,认真做事。
作者:
2018/12/4 14:33:14
9楼:
楼上正解。 不过我们一般用 ROSDK 就是这种类似的接口写法。 如果不是远程接口 var 都不用写。 但是 RO 的 var 流 输入的一个 a ,返回的肯定是 b 所以 a 和 b 都要销毁。 如果你不用 var 那么 a 的内容肯定不变。 也就没有返回内容。
----------------------------------------------
(C)(P)Flying Wang
作者:
2018/12/4 17:36:11
10楼:
但是我这样写的时候,客户端提示我 [dcc32 Error] DSClient.pas(209): E2010 Incompatible types: 'TMemoryStream' and 'TStream'
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 17:44:24
11楼:
我的环境是 delphi xe10.1 berlin + win7
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 17:47:06
12楼:
to 8楼,是的,有内存泄漏
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 17:48:13
13楼:
接 9 楼。 如果 流 不关心 输入。 那么 接口 应该用 out RO SDK 调用的时候。 变量 不需要 初始化。 RO 接口会自动初始化。 只需要记得销毁就行。
----------------------------------------------
(C)(P)Flying Wang
作者:
2018/12/4 17:48:32
13楼:
大家可以试下,是不是datasnap不支持这个写法?
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 21:59:44
14楼:
DS := TDSClient.Create(con.DBXConnection); TDSClient.Create应该还有一个重载的。后面带个boolean的参数。 你改为 DS := TDSClient.Create(con.DBXConnection, false); 试试
----------------------------------------------
学无止境
作者:
2018/12/4 22:04:09
15楼:
另外也可以这样写 TXXX.GetPhoto(out Value: TStream): Boolean;
----------------------------------------------
学无止境
作者:
2018/12/4 22:48:19
16楼:
很奇怪的问题: 1,服务端的函数如果加 out 或 var ,客户端调用提示 VAR and OUT arguments must match parameter type exactly 2. 如果不加out 或var ,客户调用提示 invalid binary storage format 3.TDSClient.Create应该还有一个重载的。后面带个boolean的参数。 --是的,如果不加false,则会有泄漏,必须加 False并手动在finlly 里释放
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 23:15:38
17楼:
客户端获取到的流大小是0了
----------------------------------------------
-把学习当信仰
作者:
2018/12/4 23:32:28
17楼:
1,服务端的函数如果加 out 或 var ,客户端调用提示 VAR and OUT arguments must match parameter type exactly //---------- 这个问题之前也遇到过,记不清是从XE的哪个版开如出这个错误的。之前是没有问题的,后来升级后就有问题了,代码没代,只是重新编译了一下。最早我好像是这样写的 TXXX.GetPhoto(out Value: TDBXStreamValue): boolean; 之所以会出现VAR and OUT arguments must match parameter type exactly这个问题,是TDBX内部有一些变化造成的。实际上也是有办法处理的,但由于担心后面会还会出其它的问题,最后来改成这样 TXXX.GetPhoto(out Value: TStream; DataSize: longword): boolean; 客户端大体上是copyfrom(v, DataSize) 关于第2个问题,后来一直没用过FD的数据集,都是转为JSON返回数据。
----------------------------------------------
学无止境
作者:
2018/12/5 10:09:53
18楼:
谢谢楼上及各位,最终还是改成了最初的形式,客户端用copystream,手动释放Dsclient和stream
----------------------------------------------
-把学习当信仰
作者:
2018/12/24 8:44:55
19楼:
DataSnap 流传输必须用 function CopyStream(const AStream: TStream): TMemoryStream; const LBufSize = $F000; var LBuffer: TBytes; LReadLen: Integer; begin Result := nil; if AStream = nil then Exit; Result := TMemoryStream.Create; try if AStream.Size = -1 then begin SetLength(LBuffer, LBufSize); repeat LReadLen := AStream.Read(LBuffer[0], LBufSize); if LReadLen > 0 then Result.WriteBuffer(LBuffer[0], LReadLen); if LReadLen < LBufSize then break; until LReadLen < LBufSize; end else Result.CopyFrom(AStream, 0); Result.Position := 0; except Result.Free; end; end;
----------------------------------------------
-只会复制粘贴!
作者:
bjzhq ( oce)
★☆☆☆☆
-
盒子活跃会员
2018/12/24 9:04:48
20楼:
to 16/17楼,DX10.2.3 已经解决了
----------------------------------------------
-