-5

このコードは、GCC -O2 コンパイラの最適化では正しく実行されませんでした。O2 最適化は、Foo オブジェクトのメモリ リークを引き起こすだけです。これは、-O3 を使用しても、最適化を行わなくても問題なく動作します。なぜこれが -O2 で動作しないのか説明してください。gcc バージョン 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) で導入された問題。コンパイラは 64 ビットで、アプリケーションも 64 ビットであることに注意してください。

#include<stdlib.h>


class Foo
{
public:
        Foo()
        {
                p_UserData = NULL;
        }
        void* p_UserData;
};

void Destroy(Foo* pFoo)
{
        long* pL = (long*)&pFoo->p_UserData;
        if(--(*pL) <= 0)
                delete pFoo;
}

int main()
{
        int i = 0;
        while( i < 10)
        {
                Foo* pFoo = new Foo();
                long* pL = (long*)&pFoo->p_UserData;
                *pL = 1;
                Destroy(pFoo);
                i++;
        }
        return 0;
}
4

2 に答える 2

2

エイリアシング ルールに違反しないバージョンのコードを次に示します。

class Foo
{
public:
    Foo() : userData(0L) { }

    long userData;
};

void Destroy(Foo* pFoo)
{
    if (--pFoo->userData <= 0)
    {
        delete pFoo;
    }
}

int main()
{
    int i = 0;
    while (i < 10)
    {
        Foo* pFoo = new Foo();
        pFoo->userData = 1;
        Destroy(pFoo);
        i++;
    }
    return 0;
}

userDataより意味のある名前に変更することをお勧めしrefCountます。

于 2013-10-01T12:10:31.387 に答える
1

-O2 最適化レベルで何が起こっているのかはわかりませんが、コードで少なくとも次の問題を確認できます。

  1. メモリが割り当てられていませんpFoo->p_UserData
  2. void*as の後に を使用するのは良い考えではないと思いますlong*
  3. Destroy() pL実際には is aのvoid**アドレスを取得しているpFoo->p_UserDataため、オブジェクトvoid*内のポインターを変更しようとしていFooます。
于 2013-10-01T10:49:54.747 に答える