在C ++中通过“删除”重用双数组指针而不会导致内存泄漏会使程序崩溃

时间:2019-04-16 15:48:33

标签: c++ pointers

在使用后,我尝试了delete的(有些可疑)约定,但这似乎不起作用。该程序应该接收单个整数的输入,对随机创建的数组进行排序,并打印经过的时间进行排序,但是当我将delete留在其中时,程序在我执行完操作后甚至没有警告就异常结束输入。换句话说,它崩溃了。但是,当我仅注释掉delete行时,该程序将完美执行。

MWE正在测量一种简单的快速排序算法的时间,由于这是一个学校项目,因此我无法更改main()函数以及使用QuickSort类及其指针等。

我唯一可以更改的是各种函数中的内容,尽管set(double*, int)似乎可以集成到构造函数中,但出于某些原因,这是不可能的选择。

目标是在构造函数中定义一个默认double*,然后将其删除并将input_array复制到this->arr中的set中:

编辑:我使用Windows 10和MinGw-w64的GCC C ++编译器。所有编译均已在Windows命令提示符中执行。

main.cpp

#include <iostream>
#include <cstdlib> // Just for good measure, though this shouldn't be needed
#include "Sort.hpp"

bool check_quick(QuickSort *quick_sort) {
    int i = 0;
    while(i < (quick_sort->size) - 1) {
        if (quick_sort->arr[i] > quick_sort->arr[i + 1]) break;
        ++i;
    } if (i == (quick_sort->size) - 1) return true;
    else return false;
}

int main() {
    int n; cin >> n;
    double *input_array = new double[n];
    srand((unsigned int)time(NULL));
    for (int k = 0; k < n; k++) input_array[k] = (double)((rand() % n));

    QuickSort* quick_sort = new QuickSort();
    quick_sort->set(input_array, n);
    quick_sort->run();
    if (check_quick(quick_sort)) {
        cout << "QuickSort is validated" << endl << endl;
    } delete quick_sort;
}

Sort.hpp

#define CLOCKS_PER_SECOND 1000
#include <iostream>
#include <ctime>
#include <iomanip> // Use to call setprecision(4)
using namespace std;

class QuickSort {
    friend bool check_quick(QuickSort*); // Give access for private variables
public:
    void print_time() const {
        cout << "QuickSort : " << fixed << setprecision(4) << seconds
             << " sec" << endl;
        // << fixed << setprecision(4) always prints to four numbers after point
    }
    QuickSort() {
        this->arr = new double[10];
        for (int i = 0; i < 10; ++i) this->arr[i - 1] = i; // Set default array
        seconds = clock(); // Set current Millisecond to starting time
    }
    ~QuickSort() {
        delete this->arr; // Delete array in object of this class
    }
    void sorter(double *arr, int begin, int end) { // Sorting Recursive Function
        // Size of array without pivot is: end - begin
        int pivot = arr[end];
            // PIVOT is element at end of subarray "arr[begin...end]"
        int i = begin, j = end;
        while (i <= j) {
            while (arr[i] < pivot) i++; // Increment until arr[i] is larger than
            while (arr[j] > pivot) j--; // Decrement until arr[j] is lesser than
            if (i <= j) { // If the larger element precedes lesser element
                swap(arr[i], arr[j]); // Call Swap function
                i++; j--;
            } // If i is larger than j now, i was 1 lesser than j before,
              // effectively leaving no more elements to scan.
        }
        if (begin < j) sorter(this->arr, begin, j); // Recursive, larger part
        if (end > i) sorter (this->arr, i, end); // Recursive, lesser part
    }
    void run() {
        sorter(this->arr, 0, this->size - 1); // Call Sorter function
        seconds = (double)(clock() - seconds) / (double)(CLOCKS_PER_SECOND);
            // Calculate Difference of Ticks and divide by Ticks per second.
            // Now, `seconds` is passed seconds with millisecond precision.
    }
    void set(double *arr, int size) {
        this->arr = new double[size]; // Make new array of `size` size
        for (int i = 0; i < size; i++) this->arr[i] = arr[i]; // Copy input_arr
        for (int i = 0; i < size; i++) cout << this->arr[i] << endl; // Copy input_arr
        this->size = size; // Save global `size` to object of class
    }
    void swap(double &p, double &q) { // Swap Function
                                      // Ampersand precedence to change input
        double x = p; // Temporary `double` saver
        p = q; // p is q
        q = x; // q is x, which is p
    }
private:
    double *arr;
    int size;
    double seconds;
};

3 个答案:

答案 0 :(得分:3)

在您的QuickSort构造函数中,您正在写要分配的数组的边界之外:

this->arr = new double[10];
for (int i = 0; i < 10; ++i) this->arr[i - 1] = i; // Set default array

在第一次迭代中,i0,因此this->arr[i - 1]写入元素-1。仅当您调用delete时,它才会崩溃,就好像您没有在运行时没有注意到此损坏并干净地退出一样。

大概只是将i-1更改为i将产生所需的行为。

答案 1 :(得分:2)

QuickSort::set的第一行:

this->arr = new double[size]; // Make new array of `size` size

泄漏在QuickSort的构造函数中分配的数组。在分配delete[]指向另一个数组之前,您需要首先arr该数组:

delete[] arr;
this->arr = new double[size]; // Make new array of `size` size

如果这是真实世界,而不是简陋的分配,那么在这种情况下最好不要使用原始指针。相反,std::vector<double>更合适。

答案 2 :(得分:2)

快速浏览发现您正在使用OnButtonUp而不是delete

此行:

  

删除此-> arr; //删除此类对象中的数组

应为:

  

delete [] this-> arr; //删除此类对象中的数组

此外,根据删除约定,您还应该这样做:

  

delete [] this-> arr;
  this-> arr = nullptr; //这很重要,否则您将被双重删除,这会带来麻烦。