【问题标题】:Function not free-ing in time功能没有及时释放
【发布时间】:2014-01-06 19:11:58
【问题描述】:

我已经查看了一些关于 SO 的其他问题,但似乎没有一个能够解决类似的问题。

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

我是 callocing 和 freeing 在中值函数内的一个数组,但 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 的问题吗?我是否过于频繁地freeing 和callocing?我不知道从哪里开始调试这个。任何帮助都会很棒!

免责声明:带有实际代码的计算机无法访问互联网。我已经尽可能准确地复制了导致问题的代码。如果缺少分号等,那是我的错,原始代码中肯定不存在。

编辑:修复了一些转录错误。我会尽快尝试获取原始代码,但从我来看现在这两个看起来都很好。

【问题讨论】:

  • free 总是“及时”释放。没有真正的SSCCE,很难在这里给出任何具体的建议......
  • 您的问题很可能是索引超出范围。 index+npt1[ii]-1 或另一个可能正在计算一个超出范围的内存地址,该地址偶然指向有效但最近释放的内存。附带说明:使用堆栈数组而不是calloc,除非您的数组必须在分配它的范围之外持续存在,或者这些数组有数兆字节大。
  • 您可能会搞砸内存,此时如果元数据损坏,free 也可能变得不可靠。
  • @SergeyL.:但是,如果发生越界访问等,Valgrind 应该 会捕获它们。 (另外,Valgrind 对栈数组没用……)
  • 这里似乎有许多可能是转录错误的错误(否则 Valgrind 会发现它们)。例如,您在npt1 中分配maxpt 元素,但尝试访问maxval 元素。此外,@Klas 在下面的答案中发现了这个错误。我认为我们真的需要在这里查看真实代码。

标签: c malloc free valgrind


【解决方案1】:

问题在于对 calcMedian 的调用。

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

应该是这样的:

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

【讨论】:

  • 看起来很合理。所以剩下的问题是:为什么 Valgrind(显然)不报告由此产生的越界访问?哦,那是如何导致正在被报告的错误报告的?
  • 嘘,就是这样!我现在感觉自己像个白痴。感谢您的所有帮助!
  • @OliCharlesworth - 我认为发生的事情是由于我传递的初始索引,数组从中间的某个地方开始,一旦数组超出范围就会报告错误。所以我只会在 calcMedian 循环中看到它。
猜你喜欢
  • 2011-02-16
  • 2014-07-05
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
相关资源
最近更新 更多