3

サードパーティのソフトウェアパッケージ(Zinc Application Framework、GUI Windowsフレームワーク、1999年頃[!])からのメモリリークを修正するのに苦労しています。私はMicrosoftVisualStudio 2005 C++を使用してWindows7マシンで作業しています(あえぎを持ってください)。誰かが何が間違っているのかについて何か洞察を持っているかどうか私は興味があります。

以下は、メモリリークがあることを示すメッセージです。

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;
}

それでも、メモリリークが発生しています。つまり、質問は次のように要約されます。ZafListに追加した後、CacheElementに割り当てられたメモリを解放するにはどうすればよいですか。提案を事前に感謝します!

4

1 に答える 1

2

コードはすべて良さそうです。

ただし、メモリリークソフトウェアがリークがあると言ったからといって、必ずしもリークがあるとは限りません。リストのデストラクタが呼び出される前に、メモリリーク検出コードがフックされている可能性があります(これは、リストがファイルスコープの静的ストレージ期間オブジェクトである場合に発生する可能性があります)。

于 2012-12-22T18:20:13.793 に答える