1

我有几个数组和一个需要删除的资源,这些变量的值在程序的整个生命周期中都会保留,它们只在单个函数中使用,因此它自然适合静态变量:

void func() {
    static GLfloat arrs[4] = {1, 1, 1, 1};
    static GLUquadric* quad = gluNewQuadric(); // delete with gluDeleteQuadric(quad)
    //... other codes ... 
}

但是,如果我使用静态,我将无法删除这些资源,因为我无法从函数外部访问这些变量。我可以制作这些全局变量,但如果可能的话,我想避免这种情况。

所以问题是:

  1. arrs[] 是堆栈分配还是堆分配?那么,我需要删除它吗?
  2. 在 GLUquadric 的情况下,显然编译器不知道如何正确删除它,现在我使用了一个运行良好的RAII包装类,但我正在寻找是否有更简单的方法。

valgrind 抱怨没有发布 GLUquadric,我想我只是清理它而不是让 valgrind 静音,即使当我释放它们时程序应该即将结束并且这些资源可能(?)在程序结束时释放.

4

7 回答 7

2
  1. 不需要删除 arrs[],它没有在堆上分配。它也不在堆栈上,它在某处的数据段中,并且是您的静态程序数据的一部分,并且会在进程执行时消失。

  2. 在堆上但一般不用担心。这种在静态初始化期间分配堆的方式不是很好,但是如果您最终需要任何析构函数调用(以摆脱外部资源等),它只会对您进行字节处理。

编辑:我仍然会担心那个堆对象。特别是如果它来自某个图书馆;你永远不知道它在内部做什么,它可能已经锁定了一些硬件资源或类似的东西。你不能在这里用智能指针等做任何事情,但如果你真的需要以这种方式分配它,可能值得用 atexit() 函数或类似函数注册释放。或者将整个事物放入带有析构函数的全局静态单例对象中。如果您知道对象只包含数据,您就不必担心,即不必担心您的堆。

于 2010-09-11T00:33:27.293 回答
1

根据您的描述,我假设这些静态变量是在使用它们的函数内部声明的。在这种情况下,您无需删除它们。事实上,如果你愿意,你不能删除它们。如果静态数据不可用,该功能将无法正常工作,因此您无法删除它。它们不是堆栈变量,因为它们的寿命超过了函数的生命周期。

于 2010-09-11T00:33:27.807 回答
1

使用自动指针:

int myFunc()
{
    static GLfloat                   arrs[4] = {1, 1, 1, 1};
    static std::auto_ptr<GLUquadric> quad    = gluNewQuadric();

    // Do Stuff
}

静态变量在首次使用时初始化。
然后在应用程序终止时将其销毁。因为它是一个智能指针,所以它会删除指针。

1:arrs[] 是堆栈分配还是堆分配?那么,我需要删除它吗?

两者都不。
不,你不需要删除它。
它具有静态存储持续时间,这仅意味着它将一直存在到主退出之后,然后与其他静态存储持续时间对象一起销毁(以创建相反的顺序)。

2:在 GLUquadric 的情况下,编译器显然不知道如何正确删除它,现在我使用了一个运行良好的 RAII 包装类,但我正在寻找是否有更简单的方法。

不,只需使用标准的,使其尽可能简单。

于 2010-09-11T00:40:55.667 回答
1

由于您的“删除”函数是一个简单的单参数函数,因此您可以直接将其shared_ptr与带有自定义删除器的 TR1(或 boost)一起使用。

void func()
{
    static std::tr1::shared_ptr<GLUQuadric> quad(gluNewQuadric(), gluDeleteQuadric);
    // ...
}
于 2010-09-11T10:19:51.543 回答
0

基本规则是我们应该只删除我们分配的任何内容。如果我们用 分配,用new释放内存delete。如果我们用 分配,用new[]释放内存delete[]

因此对于

Q1。不,不要删除。我们从未更新过它

Q2。是的,我们需要删除假设分配它的功能。然而问题在于,通过查看 Quadratic 很难知道返回的指针是仅针对一个“Quadtric”还是“Quadtric 数组”更新的,或者它只是指向某个静态变量的指针。因此,如果您动态分配内存,请使用deleteor 。delete[]

于 2010-09-11T03:41:18.227 回答
0

至于好奇和未来的参考,这是我的 RAII 模板:

template <typename T, T* constructor(), void destructor(T*)>
class Managed {
    private:
        T* value;
    public:
        Managed() {
            value = constructor();
        }
        ~Managed() {
            destructor(value);
        }
        T* operator*() {
            return value;
        }
};

它是这样使用的:

typedef Managed<GLUquadric, gluNewQuadric, gluDeleteQuadric> MGLUquadric;
static MGLUquadric quad = MGLUquadric();
gluSphere(*quad, 3.0f, 20, 20);
于 2010-09-11T10:06:29.223 回答
0

Q1 和 Q2:不要这样做!. 您不能使用std::auto_ptr<GLUquadricObj>,因为它是需要由专门的删除器释放的资源gluDeleteQuadric。通常,在像 OpenGL 和 GLU 这样的状态驱动引擎中不使用静态 - 永远不要使用它们,但在 OpenGL 上下文中,这尤其危险。

再说一次,说真的:

Q1。不要这样做。存储一个静态的 4 元素整数数组根本没有任何好处。在您需要的地方定义它。我的建议:不要使用 c 风格的数组,而是说:

const std::array<int, 4> tArray = {1, 1, 1, 1};

Q2。上面给出的 RAII 建议很好,但是您需要一个支持自定义删除器的 RAII 包装器:

std::shared_ptr<GLUquadricObj> 
 tMyQuadric(glCreateQuadric(), glDeleteQuadric);

现在随意使用它,当它们超出范围并且程序没有引用它时,它将自动关闭和销毁。哦,我看到上面的自定义 RAII 包装器也可以工作,但请:帮自己和你的追随者和同事一个忙:使用标准库结构。

于 2010-09-11T10:33:42.997 回答