0

我们的编程部门刚刚花了一个非神话般的人工月来追踪我们认为是 3rd 方组件中的错误,这是他们受版权保护的源代码:

function TGDIPPicture.GetImageSizes: boolean;
var
  multi: TGPImage;
  pstm: IStream;
  hGlobal: THandle;
  pcbWrite: Longint;

begin
  result := false;

  if Empty then
    Exit;

  if FDataStream.Size = 0 then
    Exit;

  hGlobal := GlobalAlloc(GMEM_MOVEABLE, FDataStream.Size);
  if (hGlobal = 0) then
    raise Exception.Create('Could not allocate memory for image');


  try
    pstm := nil;
    // Create IStream* from global memory
    CreateStreamOnHGlobal(hGlobal, TRUE, pstm);
    pstm.Write(FDataStream.Memory, FDataStream.Size,@pcbWrite);
    multi := TGPImage.Create(pstm);

    FWidth := multi.GetWidth;
    FHeight := multi.GetHeight;

    Result := true;

    multi.Free;
  finally
    GlobalFree(hGlobal);
  end;

end;

我们发现问题出在 TMS 的 AdvOfficeTabSet 上。如果我们添加标签,那么它会崩溃,如果我们不添加标签,那么它不会崩溃。(崩溃是那些无法调试的应用程序挂起之一,在真正的问题发生后 10 步会影响您)。

按照Raymond Chen 的建议,我用 GPTR 替换了 GMEM_MOVEABLE,它似乎已经解决了这个问题。

我想知道是否有人可以告诉我上述代码是否有任何使用 GMEM_MOVEABLE 的正当理由。AFAIK 它仅适用于剪贴板,并且应始终与 GlobalAlloc 一起使用。


当我输入这个时,另一个程序员使用我的代码在 GlobalFree 函数中遇到了错误。所以,显然这也不起作用。真的可以在这里使用一些帮助!

*CreateStreamOnHGlobal 是一个 Windows API 函数。(显然更喜欢 GMEM_MOVEABLE

*TGPImage 是 TMS 的 GDI+ 库实现的一部分。

4

1 回答 1

3

Jonathan 发现了一个明显的问题,即 HGLOBAL 的双重释放。但是正如您所发现的,使用 GMEM_MOVEABLE 是正确的。

坦率地说,代码似乎不必要地复杂。我建议您使用内置的流适配器并避免使用任何 GlobalAlloc。要获得 IStream,您只需执行以下操作:

pstm := TStreamAdapter.Create(FDataStream);

而已。

于 2013-10-29T19:38:56.767 回答