在合并排序中释放为已排序子阵列分配的内存时出错

时间:2015-04-10 22:52:50

标签: c algorithm free mergesort

我在merge_Sort()函数下面实现了合并排序。

它正确排序(当我注释掉free()调用时),但是当我尝试释放已排序子数组占用的内存时会出现问题。

/* merge_Sort() to merge array by didive and conquer*/
/* calls merge_v_1() to merge two sorted subarrays*/
/* merge_v_1() takes two sorted subarrays and copies them to new sorted array, and returns the pointer to this new sorted array*/
int *merge_Sort(int *array, int a, int b)
{
    if (a==b)
    return array;
   else
    {
         int middle = ((a+b)/2);
         int *left_Sub_Array, *right_Sub_Array;
         int *left_Sub_Array_1, *right_Sub_Array_1;

          left_Sub_Array = merge_Sort(array, a, middle);
          right_Sub_Array = merge_Sort((array + (middle - a + 1) ), middle + 1 ,b);

           left_Sub_Array_1 = left_Sub_Array;
           right_Sub_Array_1 = right_Sub_Array;

            int *newArray = malloc((b - a + 1) * (sizeof(int)));
            if (newArray == NULL)
             {
                  exit (1);
              }
             merge_v_1(left_Sub_Array_1, (middle - a + 1), right_Sub_Array_1, (b - middle), newArray);
         // PROBLEM IS HERE IN BELOW TWO FREE()
         free(left_Sub_Array);
         free(right_Sub_Array);
         return (newArray);
     }
}

最初,我认为这是因为,函数merge_v_1()正在更改指针left_Sub_Arrayright_Sub_Array。所以我想到将left_Sub_Arrayright_Sub_Array的值复制到left_Sub_Array_1right_Sub_Array_1,并将这些值传递给merge_v_1(),以便left_Sub_Arrayright_Sub_Array的值user $ ./a.out *** Error in `./a.out': free(): invalid pointer: 0x0000000002272014 *** Aborted (core dumped) user $ 不会被更改。但是,stil,我在释放内存时会遇到问题。

以下是示例输出。

{{1}}

看起来我正在尝试释放一个我不应该的记忆,但我无法弄明白它的根本原因。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

你有1个malloc和2个免费的。这总是一个问题。来自维基百科: http://en.wikipedia.org/wiki/C_dynamic_memory_allocation

  

动态内存分配的不当使用通常会成为错误的根源。这些可能包括安全漏洞或程序崩溃,   最常见的原因是分段错误。

     

最常见的错误如下:

     

不检查分配失败。内存分配不是   保证成功,并可能返回一个空指针。如果   这通常不会检查是否实施了成功的分配   由于产生的分段,导致程序崩溃   空指针取消引用上的错误。内存泄漏。没有   使用free释放内存释放不可重用内存,   程序不再使用该程序。这浪费了内存资源   并且当这些资源存在时可能导致分配失败   累。逻辑错误。所有分配都必须遵循相同的规定   模式:使用malloc分配,用于存储数据,解除分配   免费使用。无法遵守此模式,例如内存使用情况   在调用free(悬空指针)之后或者在调用malloc之前   (狂野指针),通常免费拨打两次("双免费")等   导致分段错误并导致程序崩溃。   这些错误可能是暂时的,很难调试 - 例如,释放   操作系统通常不会立即回收内存,因此   悬挂指针可能会持续一段时间并且似乎有效。

我会检查你在newArray周围的逻辑并摆脱第二个免费。

答案 1 :(得分:2)

内存分配很棘手,与性能关键代码混合(如排序)并不好。这是一个未排序数组的示例,其中包含用于临时存储的相应辅助数组。优势是2个mallocs,然后是2个释放。缺点是内存使用量为2倍。

// Code from Algorithms 4th edition - Robert Sedgewick, et al.
int main(void)
{
 int somearray[10];
 // fill with data
 int tmp_space[10];

 sort(somearray, tmp_space, 0, 9);
}


void merge(int *a, int *aux, int lo, int mid, int hi)
{
 int i = lo, j = mid+1, k;
 memcpy(&aux[lo], &a[lo], sizeof *a *((hi - lo) +1));

 // copied memory to auxiliary space. Now add back to real
 // space in proper order.
 for (k = lo; k <= hi; k++) {
  if (i > mid)
   a[k] = aux[j++];
  else if (j > hi)
   a[k] = aux[i++];
  else if (aux[j] < aux[i])
   a[k] = aux[j++];
  else
   a[k] = aux[i++];
 }
}

void sort(int *a, int *aux, int lo, int hi)
{
 if (hi <= lo) return;
 int mid = lo + ((hi - low)/2);

 // recursively break in half, and from the bottom up merge two halves.
 sort(a, aux, lo, mid);
 sort(a, aux, mid+1, hi);
 merge(a, aux, lo, mid, hi);
}