我正在努力修复来自第三方软件包(Zinc Application Framework,一个 GUI windows 框架,大约 1999 [!])的内存泄漏。我正在使用 Microsoft Visual Studio 2005 C++ 的 Windows 7 机器上工作(请屏住呼吸)。我很好奇是否有人对可能出现的问题有任何见解。
以下是我收到的消息,表明存在内存泄漏:
Detected memory leaks!
Dumping objects ->
{291} normal block at 0x003DE228, 36 bytes long.
Data: <` > 60 B6 1D 10 00 00 00 00 00 00 00 00 00 00 CD CD
Object dump complete.
The program '[3496] TempZAF3.exe: Native' has exited with code 0 (0x0).
追踪到内存分配块291,我进入如下方法:
long ZafCache::Get(long type, long value)
{
// Find a matching cache element.
CacheElement *element;
for (element = (CacheElement *)First(); element; element = (CacheElement *)element->Next())
if (element->type == type && element->value == value)
{
// Move the element to the front of the list because it is
// most recently used.
if (element != first)
{
ZafList::Subtract(element);
ZafList::Add(element, first);
}
element->useCount++;
return element->handle;
}
// Create a cache element if one didn't already exist.
long handle = CreateFunction(type, value);
element = new CacheElement(type, value, handle);
ZafList::Add(element, first);
// Remove a cache element if the cache is full.
if (++count >= size)
{
element = (CacheElement *)last;
if (element->useCount <= 0)
{
ZafList::Subtract(element);
DestroyFunction(element->type, element->value, element->handle);
delete element;
element = ZAF_NULLP(CacheElement);
count--;
}
}
return handle;
}
调试器将我带到上述方法的以下代码行:
element = new CacheElement(type, value, handle);
啊哈。至少在此方法中,此代码后面没有“删除元素”命令。显然,这是罪魁祸首——我们为 CacheElement 分配内存,而我们从未释放内存。
伟大的!因此,让我们在将元素添加到静态 ZafList 后简单地删除它,看看是否能解决问题。不——我们得到一个未处理的异常,读取某个位置的访问冲突。好的,让我们尝试一个小实验。我们将注释掉这行代码
//ZafList::Add(element, first);
并添加一个
delete element;
答对了。没有更多的内存泄漏。唯一的问题是我们实际上想要将元素添加到 ZafList。
下面是 ZafList::Add 方法的代码:
ZafElement *ZafList::Add(ZafElement *newElement, ZafElement *positionElement)
{
// Add the element to the list.
if (!first) // Put at the first of the list.
{
newElement->previous = newElement->next = ZAF_NULLP(ZafElement);
first = last = newElement;
}
else if (!positionElement) // Put at the end of the list.
{
newElement->previous = last;
newElement->next = ZAF_NULLP(ZafElement);
last->next = newElement;
last = newElement;
}
else // Put before the specified element.
{
newElement->previous = positionElement->previous;
newElement->next = positionElement;
if (!positionElement->previous)
first = newElement;
else
positionElement->previous->next = newElement;
positionElement->previous = newElement;
}
++count;
return (newElement);
}
下面是显示 ZafList 和 ZafCache 以及 ZafElement 和 CacheElement 之间关系的代码:
// Cache used for cacheing GDI pens and brushes.
class ZafCache : public ZafList
{
public:
ZafCache(int size,
long (*CreateFunction)(long type, long value),
void (*DestroyFunction)(long type, long value, long handle));
virtual ~ZafCache(void);
long Get(long type, long value);
int Release(long handle);
private:
int count;
int size;
long (*CreateFunction)(long type, long value);
void (*DestroyFunction)(long type, long value, long handle);
class CacheElement : public ZafElement
{
public:
long handle;
long type;
long value;
int useCount;
CacheElement(long type, long value, long handle);
};
};
ZafList 析构函数是否应该释放分配给 CacheElement 的内存?名义上,ZafList 析构函数似乎应该完成这项工作,因为它调用了以下方法。
void ZafList::Destroy(void)
{
ZafElement *tElement;
// Delete all the elements in the list.
for (ZafElement *element = first; element; )
{
tElement = element;
element = element->next;
delete tElement;
tElement = ZAF_NULLP(ZafElement);
}
first = last = current = ZAF_NULLP(ZafElement);
count = 0;
}
然而,我们遇到了内存泄漏。所以问题归结为:在将 CacheElement 添加到 ZafList 后,如何释放为 CacheElement 分配的内存?在此先感谢您的任何建议!