应用程序在调用SetLength时冻结

时间:2012-01-04 18:42:31

标签: delphi

这个问题可能会或可能不会解决我的问题 - 但我希望了解Delphi / Windows如何以可能导致此问题的方式运作。

我有一个使用第三方组件加载Outlook .msg文件的应用程序。

在某些情况下(特定邮件),应用程序在调用SetLength时会冻结(在组件内部,我有源代码)。 有时在从文件(流)加载属性的过程内调用setLength时会发生这种情况。它发生在同一邮件上完全相同的地方 - 并且每次都可以复制。

显然,该组件会做很多事情,这可能是其中一些副作用。但是,邮件包含我无法发送给第三方组件开发人员的机密数据,因此我无法将其发送给他进行调试。

该程序在域上的Windows XP下运行。 奇怪的是,它只发生在运行程序的用户未设置为本地计算机的管理员时。

ms := TMemoryStream.Create;
try
  WriteStorageToStream(SubStorage, ms);
  ApplyValue(ms, ms.Size)
finally
  ms.Free;
end;

procedure ApplyValue(Stream: TStream; brLen: Integer);
var
  s: AnsiString;
begin
  SetLength(s, brLen);          // this freezes it all. brLen=3512
  FillChar(s[1], brLen, #0);
  Stream.Read(s[1], brLen);
  Value := s;
end;

我不知道WriteStorageToStream究竟做了什么,但由于我们没有操纵流并且brLen有一个整数值,我认为它是无关紧要的。

2 个答案:

答案 0 :(得分:1)

SetLength绝对没有理由冻结只有3512个字符长的AnsiString。你怎么确定它在那里冻结而不是早些时候(比如在WriteStorageToSteam中)?大概是你在调试器中踩过这个。当它被冻结时,CPU是否在该进程线程上达到100%?它只在某些电子邮件上冻结的事实告诉我,这些电子邮件内容中的某些内容导致冻结。对SetLength的调用与内容无关;它只关心长度。

答案 1 :(得分:1)

我会说这是简单的内存覆盖,当调用SetLength然后尝试使用内存管理结构时,导致内存管理器失败。问题出在WriteStorageToStream(SubStorage,ms);

要找到它,请使用FastMM调试版本,并打开内存覆盖检测选项。