2013-03-11 55 views
1

我有这段代码,看看我的前台窗口是否是SDImainframe。为什么调用GetMem会导致内存泄漏?

Function Active_window_mf() :Boolean; 
var 
    FromClass: PChar; 
begin 

    MFhandle := GetForeGroundWindow; 
    GetMem(FromClass, 100); 
    GetClassName(MFhandle, PChar(FromClass), 800); 
    if StrPas(FromClass) = 'SDIMainFrame' then 
    result := true; 
end; 

但是,MADExcept报告Getmem函数有问题。任何人都可以建议,我的代码有什么问题?

+7

这个问题相当于问为什么分配记忆导致泄漏。 – 2013-03-11 16:12:31

+2

当然'MFhandle'应该是一个局部变量,它是否真的需要在所有使用一个变量... – 2013-03-11 16:17:13

+1

我会做['这个way'(http://pastebin.com/G9M6JHHF)。 @Andreas,将你的'CN'增加为256 + NULL终止符。类名最长可以有256个字符,但['GetClassName'](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633582(v = vs.85).aspx)函数需要一个可以包含NULL终止符的缓冲区。 – TLama 2013-03-11 16:20:03

回答

16

你的代码有三个问题。 首先,如果您分配内存(GetMem),你需要释放它(FreeMem):

GetMem(p, 1024); 
try 
    // Do sth with the memory 
finally 
    FreeMem(p); 
end; 

,我没有看到100800之间的关系。事实上,你说谎。您分配一个100字节的缓冲区,然后告诉Windows它足够容纳800个Unicode字符。

第三,函数的返回值是未定义的,除非比较结果为真。因此,则需要由

result := string(FromClass) = 'SDIMainFrame' 

添加result := false到过程的开始,或更换最后两行(end;前)无论如何,这是最好不要使用GetMem可言。我会这样做:

var 
    CN: array[0..256] of char; 
begin 
    GetClassName(MFhandle, CN, 256) 

此外,你应该检查错误。如果GetClassName返回0,则发生错误。因此,你可以不喜欢

function Active_window_mf(): boolean; 
var 
    CN: array[0..256] of char; 
begin 
    result := false; 
    if GetClassName(GetForegroundWindow, CN, 257) > 0 then 
    result := string(CN) = 'SDIMainFrame'; 
end; 

更新:据大卫的约抽象层次良好的出发点,这将是很好做这样的:

function ClassNameFromHWND(const Handle: HWND): string; 
var 
    CN: array[0..256] of char; 
begin 
    result := ''; 
    if GetClassName(Handle, CN, 257) > 0 then 
    result := CN; 
end; 

function Active_window_mf(): boolean; 
begin 
    result := ClassNameFromHWND(GetForegroundWindow) = 'SDIMainForm'; 
end;