修复涉及派生类和静态类的C ++内存泄漏

时间:2012-12-22 18:07:09

标签: c++ memory-leaks

我正在努力修复来自第三方软件包的内存泄漏(Zinc Application Framework,一个GUI窗口框架,大约在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);

啊哈。此代码后面没有“delete element”命令,至少在此方法中是这样。显然,这是罪魁祸首 - 我们为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;
}

然而我们的内存泄漏了。所以问题归结为:在将其添加到ZafList后,如何释放为CacheElement分配的内存?在此先感谢您的任何建议!

1 个答案:

答案 0 :(得分:2)

代码看起来都不错。

但仅仅因为内存泄漏软件说存在泄漏并不一定意味着存在泄漏。可能是在调用列表的析构函数之前挂起了内存泄漏检测代码(如果列表是文件范围静态存储持续时间对象,则会发生这种情况。)