删除指针向量时,调试断言失败

时间:2018-09-08 11:16:38

标签: c++

我有一个vector,其中有pointer个课程:

vector<Entity*> editorElements;
vector<Entity*> entities;
vector<DirectionalLight*> dirLights;
vector<PointLight*> pointLights;
vector<SpotLight*> spotLights;

此代码在我的课程Scene中。 Scene的ctor和析构函数如下:

Scene()
{
    editorElements = vector<Entity*>();
    entities = vector<Entity*>();
    dirLights = vector<DirectionalLight*>();
    pointLights = vector<PointLight*>();
    spotLights = vector<SpotLight*>();
}

~Scene()
{
    delete[] &entities;  // ERROR HERE
    delete[] &dirLights;
    delete[] &pointLights;
    delete[] &spotLights;
    delete[] &editorElements;
}

在析构函数中,我标记了一行ERROR HERE。我先输入哪个向量都没有关系,但我总是会得到错误。 奇怪的是,直到最近(没有触及Scene类或使用Scene实例的任何其他类中的任何东西),它的工作状况都很好,突然间它引发了一个异常:

enter image description here

vector是否为空或是否具有元素都没有关系,它给出的错误都相同。

我需要协助才能解决此问题。

3 个答案:

答案 0 :(得分:2)

向量不是更新的指针,更不用说更新的数组了。因此,您不应该删除它们。 如果 ,您需要调用向量中存储的指针的delete,则应遍历向量,删除每个元素。但是最好改为存储智能指针(例如router.post('/checkAuth', function (req, res) { console.log(req.body.key) if (!req.body.key) { console.log('enter') } jwt.verify(req.body.key, 'MatchaSecretKey', function(err, decoded) { if (err) { res.send({'result': false}) } else { res.send({'result': true}) } }) }); 。那就是如果您需要存储所有指向动态分配对象的指针。

请注意,如果最终删除了析构函数中的元素,则还需要注意rule of three/five

答案 1 :(得分:2)

delete expression delete [] x的描述如下:

  

销毁由new []-表达式创建的数组

因此,如果delete[] &entities是由&entities表达式创建的数组,那么new[] 才有意义。对吧?

但是entitiesstd::vector<Entity*>,而不是Entity[]。您没有使用new[]创建它,因此您绝对不能使用delete[]删除它。

std::vector不是数组的语法糖,它是模板类,而std::vector<Entity*> entities不是数组,它是具有构造函数和析构函数的对象。那也告诉我们这句话

entities = vector<Entity*>();

没有任何用处-entities是一个对象,因此它已经是默认构造的。您只是默认构造一个相同类型的匿名临时文件,然后对其进行分配。

最后,在这里将原始指针存储在向量中是可以的,因为向量不负责对象的生存期。在大多数情况下,最好让向量拥有对象,这样您就不必担心直接通过

手动删除它们
vector<Entity>

或间接

vector<unique_ptr<Entity>>

NB。一个很好的指导原则是:根本不要在用户代码中使用newnew[]deletedelete[]

>

使用类对象来管理您的存储,因为编译器将为您调用其构造函数和析构函数。

如果您需要一个自定义类,请编写一个仅用于 来管理内存的类,以免与程序逻辑脱钩。否则,如果您确实需要所有权模型等,请使用标准的库工具,例如std::vectorstd::arraystd::unique_ptrstd::shared_ptr

答案 2 :(得分:1)

  

突然间它引发了异常

这是因为尝试删除不应该删除的内容。 The delete[] syntax用于删除动态分配的 array 。但是,您为它提供了一个指向std::vector实例的指针。因此,编译器将此地址当作删除对象,就好像它是一个数组一样,其中包括找出其大小,然后删除整个段。但是没有合适的数字,因为它不是数组,所以在运行时,您最终试图在没有访问权限的地方删除某些内容,因此断言失败,因为这是访问违反,又名段错误。

此外,vector是一个管理自己的内存的类。如果要释放保存在此容器中的实体(即,动态分配的各个元素本身),则应遍历它们并删除每个元素。方便地,例如,使用autorange-based for loop像这样:

for (auto ptr : entities)
    delete ptr;

但是,在大多数情况下,您最好节省自己的内存管理开销,并选择std::unique_ptr 而不是原始指针:

#include <memory>
...
std::vector<std::unique_ptr<Entity>> entities;

通过这种方式,您不必担心释放任何内存,因为std:: unique_ptr一旦被销毁就会被释放,这是vector销毁的一部分。

此外,这是不必要的,可能不是您打算要做的:

entities = vector<Entity*>();

由于vector对象本身已经在此行之前定义了(因此存在),并且它所做的就是创建一个相同的新对象并将其分配给entities