-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*if 之后使用它不是一个好主意long*
  3. 实际上Destroy() pL是 a void**,因为您正在获取pFoo->p_UserDatathat is的地址void*,因此您正在尝试更改Foo对象内的指针。
于 2013-10-01T10:49:54.747 回答