具有向量成员的对象的破坏

德文

我最近在用vector作为成员编码类时遇到了一个奇怪的错误。该错误由我自己介绍,但是运行时结果令我震惊。简化示例如下所示。

基本上,该错误存在于构造函数中,该构造函数h2的大小仅为,dimension_而不是dimension_*dimension_,这导致对h2invoid A::set()和的超出范围的访问double A::get()我承认有这种错误对我来说是不好的。我会认为它应该出现的情况是h[2],并h[3]void A::set()将访问一些随机的内存地址,或只是在载体的保留范围h2但是真正发生的是,当析构函数被称为free()错误时,会引发一个错误,然后是很多虚拟的Backtrace,我不想在这里列出。

*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x0000000001637040 ***

但是,如果我不访问h[3]void A::set(),不会出现这种情况。我的问题是向量和析构函数到底发生了什么?向量的析构函数是否知道我访问了哪些元素?我认为向量仅在调用析构函数时才知道其大小并释放内存。任何想法将不胜感激。谢谢。

以下是显示运行时错误的示例代码。

#include<vector>
#include<cstddef>
#include<iostream>

class A
{
    public:
        A(size_t dimension);
        virtual ~A();
    public:
        virtual double get();
        virtual void set();
    protected:
        const size_t dimension_;
        std::vector<double> h1, h2;
};

A::A(size_t dimension):
    dimension_(dimension),
    h1(dimension_*dimension_),
    h2(dimension)
{}

A::~A()
{
}

double A::get()
{
    set();
    double result(0), temp(0);
    for(size_t i(0); i < dimension_; ++i)
    {
        temp = 0;
        for(size_t j(0); j < dimension_; ++j)
            {   
                temp += h1[j] * h2[j + i*dimension_];
            }   
        result += temp * h1[i];
    }
    return result;
}

void A::set()
{
    h1[0] = h1[1] = h1[2] = h1[3] = 0.5;
    h2[0] = h2[1] = h2[2] = h2[3] = 0.005;
}

int main()
{
    A mya(2);
    std::cout << mya.get() << "\n";
    return 0;
}
光碟

operator[]用超出范围的参数调用向量的会导致未定义的行为(UB),因此从技术上讲,任何事情都可能发生,包括您所发生的情况。一旦您调用UB,所有的赌注都将关闭。您无法提前推断出调用UB的代码的效果。

请注意,at()如果您尝试访问越界元素,则该方法将进行边界检查,并会引发异常。如果您确实访问了一个超出范围的元素,那么此时您将获得一个异常,这使得调试更加容易。缺点是边界检查会花费一些额外的时间,因此,如果您要进行数百万个向量访问,则可能会发现at()它比慢一些operator[]权衡是否值得取决于您。


话虽如此,可能正在发生的事情是您破坏了C ++实现的堆分配器使用的某些簿记结构。堆分配器通常会分配比请求更多的内存,并使用额外的空间来存储有关分配本身的数据。

当向量释放用于保留向量中元素的分配时,分配器会发现其簿记数据已被破坏,因此您将获得此断言。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何初始化静态向量成员?

来自分类Dev

如何在类定义中初始化向量成员变量?

来自分类Dev

如何使用初始化列表来初始化2D向量成员?

来自分类Dev

VS2013:优化具有向量成员的类的移动语义的潜在问题?

来自分类Dev

是否具有虚拟成员的对象类?

来自分类Dev

如何在类模板的构造函数中初始化向量成员变量

来自分类Dev

具有受保护成员的自定义对象的排序向量

来自分类Dev

如何修改向量成员的值?

来自分类Dev

将unique_ptr的向量传递给对象。向量成为成员变量。正确的方法?

来自分类Dev

如何使用多态从基类访问派生类向量成员?

来自分类Dev

检查两个匹配元素之间是否找到向量成员

来自分类Dev

动态调用向量中所有对象的C ++类成员

来自分类Dev

指向具有多个对象的成员函数的指针的向量C ++

来自分类Dev

具有常量成员的默认构造函数

来自分类Dev

具有可变成员的constexpr对象

来自分类Dev

具有unique_ptr成员的对象的错误C2280向量

来自分类Dev

搜索向量成员的前n%个C ++

来自分类Dev

是否有用于检查向量成员资格的R函数?

来自分类Dev

连接列表中两个向量成员的数据

来自分类Dev

具有unique_ptr成员和自定义析构函数的对象的向量

来自分类Dev

初始化后,Const_iterator成员变量未指向向量成员变量的开头

来自分类Dev

复制具有列表成员的对象列表

来自分类Dev

是否具有虚拟成员的对象类?

来自分类Dev

VS2013:优化具有向量成员的类的移动语义的潜在问题?

来自分类Dev

无法访问类的向量成员

来自分类Dev

具有变量成员的树上的Haskell树折叠

来自分类Dev

访问变量成员

来自分类Dev

私有类型的静态常量成员

来自分类Dev

具有 const 向量成员的类的复制构造函数

Related 相关文章

  1. 1

    如何初始化静态向量成员?

  2. 2

    如何在类定义中初始化向量成员变量?

  3. 3

    如何使用初始化列表来初始化2D向量成员?

  4. 4

    VS2013:优化具有向量成员的类的移动语义的潜在问题?

  5. 5

    是否具有虚拟成员的对象类?

  6. 6

    如何在类模板的构造函数中初始化向量成员变量

  7. 7

    具有受保护成员的自定义对象的排序向量

  8. 8

    如何修改向量成员的值?

  9. 9

    将unique_ptr的向量传递给对象。向量成为成员变量。正确的方法?

  10. 10

    如何使用多态从基类访问派生类向量成员?

  11. 11

    检查两个匹配元素之间是否找到向量成员

  12. 12

    动态调用向量中所有对象的C ++类成员

  13. 13

    指向具有多个对象的成员函数的指针的向量C ++

  14. 14

    具有常量成员的默认构造函数

  15. 15

    具有可变成员的constexpr对象

  16. 16

    具有unique_ptr成员的对象的错误C2280向量

  17. 17

    搜索向量成员的前n%个C ++

  18. 18

    是否有用于检查向量成员资格的R函数?

  19. 19

    连接列表中两个向量成员的数据

  20. 20

    具有unique_ptr成员和自定义析构函数的对象的向量

  21. 21

    初始化后,Const_iterator成员变量未指向向量成员变量的开头

  22. 22

    复制具有列表成员的对象列表

  23. 23

    是否具有虚拟成员的对象类?

  24. 24

    VS2013:优化具有向量成员的类的移动语义的潜在问题?

  25. 25

    无法访问类的向量成员

  26. 26

    具有变量成员的树上的Haskell树折叠

  27. 27

    访问变量成员

  28. 28

    私有类型的静态常量成员

  29. 29

    具有 const 向量成员的类的复制构造函数

热门标签

归档