c++ - 使用 vector 成员破坏对象

标签 c++ vector free destructor

我最近在编码以 vector 为成员的类时遇到了一个奇怪的错误。这个bug是我自己引入的,但是运行结果让我震惊。简化的示例如下所示。

基本上,该错误存在于构造函数中,其中 h2 的大小仅为 dimension_ 而不是 dimension_*dimension_,这会导致 out- void A::set()double A::get() 中的 h2 的范围外访问。我承认有这样的bug是我的错。我认为应该发生的是 void A::set() 中的 h[2]h[3] 将访问一些随机内存地址或 vector h2的保留范围内。但真正发生的事情是,当调用析构函数时,会引发 free() 错误,随后会出现大量虚拟回溯,我不想在这里列出。

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

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

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

#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;
}

最佳答案

调用 vector 的operator[]超出范围的参数会导致未定义的行为 (UB),因此从技术上讲任何事情都可能发生,包括您的案例中发生的情况。一旦你调用 UB,一切就都结束了;您无法提前推断调用 UB 的代码的效果。

请注意 at()方法将进行边界检查,如果您尝试访问越界元素,则会抛出异常。如果您确实访问了越界元素,您将立即收到异常,这使得调试更加容易。缺点是边界检查需要一些额外的时间,因此如果您正在进行数百万次 vector 访问,您可能会注意到 at()operator[]< 慢一点。这种权衡是否值得取决于您。


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

当 vector 释放用于保存 vector 中元素的分配时,分配器发现其簿记数据已被破坏,因此您最终会得到此断言。

关于c++ - 使用 vector 成员破坏对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26491416/

相关文章:

c++ - 在 C++ 中,我是否可以将整数指针传递给将整数数组作为参数的函数?

c++ - 如何声明返回标准迭代器的函数原型(prototype)?

r - 矩阵中向量-向量的频率

c - 在 C 中带有参数的 free() 语法

c++ - boost 属性树 毫无意义的错误路径

c++ - 安全地取消 boost asio 截止时间计时器

C++ 堆栈内存未被释放

c++ - 是否允许将 std::vector 的元素插入到同一 vector 中?

c - 传递指针的free() 'know'如何有效?

C 自由函数(不使用 malloc)