我的代码漏了。我该如何解决?

时间:2014-03-22 15:34:28

标签: c++ recursion memory-leaks new-operator mergesort

我的代码漏了。我应该删除数组的某个地方,我在这行中分配的内容: T* out_array = new T[size1+size2]; 但我不知道在哪里以及如何。 有人可以帮帮我吗?

代码:

#include <iostream>
using namespace std;

template <class T>
T* merge(T arr1[], int size1, T arr2[], int size2);

template <class T>
T* merge_sort(T arr[], int n)
{
    if(n < 2){return arr;}
    int mid = n/2;
    T *arr1 = merge_sort<T>(arr,mid);
    T *arr2 = merge_sort<T>(arr+mid,n-mid);
    return merge(arr1, mid, arr2, n-mid);
}

template <class T>
T* merge(T arr1[], int size1, T arr2[], int size2)
{
    int i = 0,j = 0;

    T* out_array = new T[size1+size2];

    while((i < size1) && (j < size2))
    {
        if(arr1[i] >= arr2[j])
        {
            out_array[i+j] = arr2[j];
            ++j;
        }
        else
        {
            out_array[i+j] = arr1[i];
            ++i;
        }
    }
    while(i < size1)
    {
        //copy the reminder
        out_array[i+j] = arr1[i];
        i++;
    }
    while( j < size2)
    {
        out_array[i+j] = arr2[j];
        j++;
    }

    return out_array;
}

int main()
{
    int a[] = {2, 42, 3, 7, 1};
    int *a2 = merge_sort(a,5);
    for (int i = 0; i<= 4 ; ++i) cout << a2[i] << endl;
    delete[] a2;
    return (0);
}

4 个答案:

答案 0 :(得分:1)

这些都在泄漏:

T *arr1 = merge_sort<T>(arr,mid);
T *arr2 = merge_sort<T>(arr+mid,n-mid);

修复:

template <class T>
T* merge_sort(T arr[], int n)
{
    if(n < 2){return arr;}
    int mid = n/2;
    T *arr1 = merge_sort<T>(arr,mid);
    T *arr2 = merge_sort<T>(arr+mid,n-mid);
    T * res = merge(arr1, mid, arr2, n-mid);
    delete[] arr1;
    delete[] arr2;
    return res;
}

答案 1 :(得分:1)

在尝试解决实现中的内存泄漏问题之前,请考虑以下问题:每次调用out_array时是否真的有必要为merge()分配内存?

我认为答案是否定的,相反,在arr中为辅助数组分配内存(与merge_sort()相同)一次就足够了,并传递此数组到merge()。这种方法可以大大减少内存分配的次数,并且更容易管理内存分配。

答案 2 :(得分:1)

我记得在紧急情况下干预&#34;对于泄漏严重的应用程序:

  • 需要快速加载的改进
  • 该应用程序已经泄漏,但不太糟糕
  • 已知非回归不完整
  • 应用程序从未在valgrind下运行(在valgrind下运行具有严格超时依赖性的多线程代码并非易事......)

那么,我做了什么?我使用grep并从代码(*)中删除了对new的所有调用。

  • 在C ++ 03中:delete是错误(**)而new是代码气味
  • C ++ 11中的
  • deletenew都是错误(**)

并不奇怪,所有内存泄漏都消失了!

您可以使用:

,而不是使用new
  • std::vector表示动态分配的数组
  • std::unique_ptr表示动态分配的对象
  • std::shared_ptr在一些罕见且神秘的情况下,对象的实际生命周期遵循复杂的规则

    (*)或者我可以拥有它,如果它是C ++ 11,在C ++ 03中,并且在没有完美转发和变量模板的情况下,make_auto_ptr实际上是不可能的。

    (**)在C ++ 03中,可以认为专家写boost::scoped_ptr(或等价物)可能需要它;在C ++ 11中,您可以在unique_ptr之上构建每个抽象,因为它的成本为0。

答案 3 :(得分:0)

如果要分配这样的内存,则应使用std::unqiue_ptr。改变

T* out_array = new T[size1+size2];

std::unique_ptr<T[]> out_array(new T[size1 + size2]);

更改merge_sort签名以返回unique_ptr<T[]>,修复arr1和arr2类型,并且不要手动删除它。这种方法比使用delete[]更好,因为可以在T operator =中生成异常。比,delete[]运算符永远不会被调用,即使你在Erik的答案中添加了删除,你仍然会泄漏内存。