带有GMEM_MOVEABLE的globalalloc对Delphi中的局部变量是危险的吗?

时间:2013-10-29 18:28:56

标签: delphi winapi memory gdi+ tms

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

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's advice我用GPTR和替换GMEM_MOVEABLE似乎解决了问题。

我想知道是否有人可以告诉我上述代码是否有合理的理由使用GMEM_MOVEABLE。 AFAIK只适用于剪贴板,它应该始终与GlobalAlloc一起使用。


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

* CreateStreamOnHGlobal是一个Windows API函数。 (显然prefers GMEM_MOVEABLE

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

1 个答案:

答案 0 :(得分:3)

Jonathan发现了一个明显的问题,那就是HGLOBAL的双重自由。但正如您所发现的,使用GMEM_MOVEABLE是正确的。

坦率地说,代码似乎不必要复杂。我建议你使用内置的流适配器,避免任何GlobalAlloc。要获得IStream,您只需要这样做:

pstm := TStreamAdapter.Create(FDataStream);

就是这样。