功能不能及时释放

时间:2013-12-18 14:37:48

标签: c malloc free valgrind

我已经看了一些关于SO的其他问题但是它们似乎都没有解决类似的问题。

我有一个函数对数组进行排序(使用堆排序)并计算中位数。堆排序例程直接来自Numerical Recipies。

我是callocfree中位函数内的数组,但free似乎没有及时释放空间。这里有一些代码来说明我的意思:

int calcMedian(int n1, int n2, int *dat) 
{
   int ii, npt;
   int *inparr, retval;

   npt    = n2 - n1 + 1; /* Number of elements in array */
   inparr = calloc(npt+1, sizeof(*inparr));

   for(ii = n1; ii <= n2; ii++)
      inparr[ii-n1+1] = dat[ii]; /* ii-n1+1 because heapsort function likes arrays to
                                 start from 1 */

   heapsortInt(npt, inparr); /* The error isn't here, function has been previously 
                                debugged. Sorting is in-place.*/
   if (npt % 2)
      retval = inparr[(npt+1)/2];
   else
      retval = (inparr[npt/2]+inparr[npt/2+1])/2;

   free(inparr);
   return(retval);
}

函数heapsortInt已经过彻底调试,并且已经在其他几个地方使用而没有问题。现在我在一个循环中调用我的函数calcMedian

for(ii = 0; ii < maxval; ii++) {
   index = ii * maxpt;
   med1 = calcMedian(index, index+npt1[ii]-1, data1+index);
   med2 = calcMedian(index, index+npt2[ii]-1, data2+index);
}

其中相关变量定义如下:

int *data1, *data2;
int *npt1, *npt2;

data1 = calloc(maxval * maxpt, sizeof(*data1));
data2 = calloc(maxval * maxpt, sizeof(*data2));

npt1  = calloc(maxval, sizeof(*npt1));
npt2  = calloc(maxval, sizeof(*npt2));

所以我基本上将一个大数组的不同部分传递给calcMedian并返回必要的中值。

问题: calcMedian在遇到第二个函数调用时似乎崩溃了。我通过valgrind运行它,这就是它告诉我的:

Invalid read of size 4
at 0x43F67E: calcMedian /* Line no. pointing to calloc in calcMedian */
by 0x4416C9: main /* Line no pointing to second call of calcMedian */
Address 0x128ffdc0 is 6,128 bytes inside a block of size 110,788 free'd 
at 0x4A063F0: free
by 0x43F728: calcMedian /* Line no. pointing to free in calcMedian */
by 0x4416C9: main /* Line no pointing to first call of calcMedian */

这是free的问题吗?我是freecalloc过于频繁吗?我不知道从哪里开始调试这个。任何帮助都会很精彩!

免责声明:具有实际代码的计算机无法访问互联网。我在这里尽可能准确地再现了导致问题的代码。如果有任何遗漏的分号等是我的错,那么原始代码中肯定没有。

编辑:修正了一些转录错误。我会尝试尽快获得原始代码,但是从我看来它们现在看起来很好。

1 个答案:

答案 0 :(得分:3)

问题是对calcMedian的调用。

您正在添加索引两次,一次在调用中,然后在calcMedian中。

应该是这样的:

med1 = calcMedian(index, index+npt1[ii]-1, data1); 
med2 = calcMedian(index, index+npt2[ii]-1, data2);