【发布时间】:2013-10-29 18:28:55
【问题描述】:
我们的编程部门刚刚花了一个非神话般的人工月来追踪我们认为是第 3 方组件中的错误,这是他们受版权保护的源代码:
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+ 库实现的一部分。
【问题讨论】:
-
您将
TRUE传递给CreateStreamOnHGlobal()以获取fDeleteOnRelease参数,这意味着流现在拥有内存句柄,您不应自己调用GlobalFree()。您似乎也没有释放流(除非 Delphi 自动为您这样做,或者TGPImage.Create这样做?如果是这样,您将肯定最终获得双重释放内存句柄)。我不知道这些事情是否会导致您的崩溃,但在这种情况下使用GMEM_MOVEABLE并没有固有的问题,所以我很确定这不是问题。 -
这是真正的代码吗?它有很多问题。不分配结果值。缺少错误检查。等等。我们如何确定 GlobalAlloc 甚至是问题所在。
-
谢谢,这就是我们第三次尝试使用我们根本不想使用的功能的尝试!我尝试在 CreateStreamOnHGlobal 中将 TRUE 更改为 false 并遇到不同的问题,一些 realloc 的事情,希望你所说的是正确且唯一的答案。
-
@DavidHeffernan 是的,它来自 TMS,我想我通过发布此内容侵犯了某些版权,但它应该被修复,而且它不够新颖,不足以关心版权。如果可能的话,我宁愿不使用全局变量——对我来说改变不会太多。
-
很难相信 TMS 这么写的。这是牛肚。
标签: delphi winapi memory gdi+ tms