析构函数导致堆损坏。

时间:2017-03-30 19:07:50

标签: c++ destructor

我正在使用析构函数,我不明白为什么在main函数终止时我为此代码收到错误。

#include <iostream>
#include <math.h>
#include <string>
#include <cstdint>
#include <cassert>
using namespace std;

class RGBA {
    uint8_t _red, _blue, _green, _alpha;
    int *_arr;
    int _length;
public:
    RGBA(int *arr, int length, uint8_t r = 0, uint8_t b = 0, uint8_t g = 0, uint8_t a = 255): 
      _red (r), _blue (b), _green (g), _alpha (a) {
      _arr = arr;
      _length = length;
      }
      ~RGBA() {
          cout << "Destroying object" << endl;
          delete[] _arr;
      }

    void print() {
        for (int i = 0; i < _length; ++i) {
            cout << _arr[i] << endl;
        }
        cout << static_cast<int>(_red) << " " << static_cast<int>(_blue) << " " << static_cast<int>(_green) << " " << static_cast<int>(_alpha) << endl;
    }
};


int main() {
    int arr[3] = {1,2,3};
    RGBA rgba(arr, 3);
    rgba.print();

    cin.get();
    return 0;
}

它输出,但是当我按Enter键时,它会输出“销毁对象”,并显示以下错误“这可能是由于堆的损坏,这表明testcpp.exe或它具有的任何DLL中的错误装。“

1
2
3
0 0 0 255

我在Win7上使用VS2010。

5 个答案:

答案 0 :(得分:6)

当封闭功能退出时,自动存储持续时间变量int arr[3]将自动解除分配。

尝试delete[]会导致未定义的行为。只有new[]分配的对象才能使用delete[]取消分配。

答案 1 :(得分:4)

在您的情况下,这实际上是正在发生的事情:

int arr[3] = {1,2,3};
delete[] arr;

arr中的main处于自动存储状态。您将它传递给您的对象,该对象假设所有权并假定内存是使用new动态分配的。

您应该只delete [] new []

答案 2 :(得分:1)

您传递的数组arr正在主函数的堆栈中分配。然后,将指针传递给RGBA实例,然后在其析构函数中删除该数组。由于它首先没有动态分配,这是一件坏事。

在析构函数中删除数组表示您要将数组的所有权传输到该类。为此,您需要传递动态分配的数组或在构造函数中分配新数组,并复制通过参数传递的数组的内容。

如果您不需要所有权,只需在析构函数中删除删除调用。

答案 3 :(得分:1)

~RGBA() {
    cout << "Destroying object" << endl;
    delete[] _arr;
}

这是你的问题,因为删除对静态数组不起作用,它总是适用于动态数组。 delete仅适用于new

int *arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

这将完美地运作。

答案 4 :(得分:0)

那是因为你不应该删除数组。

析构函数的实现是正确的,但数组未使用new[]分配,因此您不能使用delete[]取消分配。

如果您使用现代化的堂兄std::array替换主阵列中的数组,以及std::vector类中的指针,您会看到将数组指定给矢量需要堆上的分配和数组中每个元素的副本。

修复代码的一种快速方法是使用new[]分配数组:

int* arr = new int[3]{1, 2, 3};
RGBA rgba(arr, 3);
rgba.print();

现在使用new[]分配数组,可以使用delete[]安全地删除它。

但请注意,在大多数现代代码中,您可以使用std::array<T, N>std::vector<T>std::unique_ptr<T[]>来管理数组。

使用数组和向量的结果代码如下:

#include <iostream>
#include <vector>
#include <array>

struct RGBA {
    std::uint8_t red = 0, green = 0, blue = 0, alpha = 255;
    std::vector<int> arr;

    RGBA(std::vector<int> _arr) : arr{std::move(_arr)} {}

    // No destructor needed. vector manages it's own resources.

    void print() {
        for (auto&& number : arr) {
            std::cout << number << std::endl;
        }

        std::cout << static_cast<int>(red) << " "
                  << static_cast<int>(blue) << " "
                  << static_cast<int>(green) << " "
                  << static_cast<int>(alpha) << std::endl; 
    }
};

int main() {
    // Create a constant array on the stack the modern way
    constexpr std::array<int, 3> arr{1, 2, 3};

    // Copy array elements in the vector
    RGBA rgba{std::vector<int>{arr.begin(), arr.end()}};

    rgba.print();

    cin.get();
}