【发布时间】:2016-11-29 20:41:23
【问题描述】:
即使调用了 array->Release,UIAutomation FindAll 函数也会泄漏我系统上的内存。请参阅下面示例程序中的“内存泄漏”。我已经对堆栈溢出进行了一些搜索,并且我看到一些关于内存垃圾收集的 cmets 需要大约 3 分钟才能开始工作,但我看到的是内存泄漏。请注意,下面的程序没有 malloc 或 new。 我正在使用带有 Service Pack 1 的 Windows 7。cl 版本是: Microsoft (R) 32 位 C/C++ 优化编译器版本 16.00.40219.01 用于 80x86。
/* Program to demonstrate that IUIAutomation function FindAll leaks memory.
* Build with: cl uia_memleak.cpp user32.lib ole32.lib oleaut32.lib
*/
#include <windows.h>
#include <stdio.h> /* for fprintf */
#include <assert.h> /* for assert */
#include <UIAutomation.h>
#include <oleauto.h>
/* Forward declarations */
void loop_get_buttons(IUIAutomation * pui, HWND hwnd, int iterations);
int get_buttons(IUIAutomation * pui, HWND hwnd);
BOOL button_appender(IUIAutomation * pui, IUIAutomationElement * root);
BOOL button_condition_appender(IUIAutomation * pui, IUIAutomationElement * root, IUIAutomationCondition * condition);
int
main(int argc, char *argv[])
{
int i;
HRESULT hr;
IUIAutomation *pui;
CoInitialize(NULL);
hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void **)&pui);
assert(hr == S_OK);
fprintf(stdout,
"Open the Task Manager to observe the memory consumed by this program. Press Enter and then open and select the calc program. You should see the Memory column increasing slowly. This program will complete in under a minute.\n");
getchar();
for (i = 0; i < 100; i++) {
HWND hwnd;
hwnd = GetTopWindow(NULL);
loop_get_buttons(pui, hwnd, 500);
}
fprintf(stdout, "Press Enter to quit.\n");
getchar();
CoUninitialize();
return 0;
}
void
loop_get_buttons(IUIAutomation * pui, HWND hwnd, int iterations)
{
int i;
for (i = 0; i < iterations; i++) {
get_buttons(pui, hwnd);
}
}
int
get_buttons(IUIAutomation * pui, HWND hwnd)
{
HRESULT hr;
IUIAutomationElement *root = NULL;
hr = pui->ElementFromHandle(hwnd, &root);
assert(hr == S_OK);
button_appender(pui, root);
root->Release();
return 0;
}
BOOL
button_appender(IUIAutomation * pui, IUIAutomationElement * root)
{
/* Returns FALSE on success, TRUE on error. */
HRESULT hr;
VARIANT varProp;
IUIAutomationCondition *condition;
assert(root != NULL);
varProp.vt = VT_I4;
varProp.lVal = UIA_ButtonControlTypeId;
hr = pui->CreatePropertyCondition(UIA_ControlTypePropertyId, varProp, &condition);
assert(hr == S_OK && condition != NULL);
button_condition_appender(pui, root, condition);
condition->Release();
VariantClear(&varProp);
return FALSE;
}
BOOL
button_condition_appender(IUIAutomation * pui, IUIAutomationElement * root,
IUIAutomationCondition * condition)
{
/* Returns FALSE on success, TRUE on error. */
HRESULT hr;
IUIAutomationElementArray *array = NULL;
assert(root);
hr = root->FindAll(TreeScope_Descendants, condition, &array); /* memory leak */
assert(hr == S_OK);
if (array)
array->Release();
return FALSE;
}
【问题讨论】:
-
任务管理器显示内存增加并不表示存在“泄漏”。
-
在这种情况下需要注意几点。首先,如果您删除 FindAll 调用,则无论调用 get_buttons 的次数如何,任务管理器显示的内存都是恒定的。其次,上述脚本消耗的内存量取决于调用 get_buttons 的次数。因此,我的假设是 FindAll 存在内存泄漏。您有其他假设吗?
标签: c++ c memory-leaks ui-automation