指针错误无效

时间:2012-06-01 14:54:37

标签: c pointers memory-management free

我在R函数中嵌入了一些C代码,它们以相同的方式保持sigsegging,但在不同的点(通过程序进展 - 似乎总是来自同一个函数)。

这就是事情 - 我得到的错误是;

*** glibc detected *** /packages/R/2.15.0/lib64/R/bin/exec/R: munmap_chunk(): 
invalid pointer: 0x0000000014059b20 ***

现在这是一个非常标准的错误(munmap_chunk()free()的一部分,如果我记得的话) - 奇怪的是错误来自一个从内部释放一组数组的函数一个struct(程序在正常运行过程中分配和释放数百万个结构)。

该功能如下所示;

multifit_work_t *free_multifit(multifit_work_t *work)
{

  if (work == NULL || work->u==NULL || work->w==NULL || work->v==NULL || work->b==NULL || work->rv1==NULL) {
    fprintf(stderr,"ERROR: Internal array in multifit_work_t object was already NULL\n");
    exit(1);
  }

  // each of the work->* arrays are just an array of doubles of length 1 or more.

  // LOGGING FUNCTIONALITY: Here, prints out the address and values of each 
  // of the arrays

  // free each array first
  free(work->u);
  free(work->w);
  free(work->v);
  free(work->b);
  free(work->rv1);
  free(work);

  // LOGGING FUNCTIONALITY: Here prints an, "Exiting free_multifit()" message

  return NULL;
}

所以我在释放它之前检查每个指针。我在日志记录功能中添加了输出每个数组的地址和初始值。对于违规指针生成上述错误的崩溃日志文件,我得到了很多命中(可以理解的是,我们在释放后重新使用相同的内存位置);

$: grep 14059b20 logfile.txt
....
194624) work->b: ADDRESS: [0x14059b20] VALUE: [-5.620804e-02]
194629) work->b: ADDRESS: [0x14059b20] VALUE: [2.759472e+00]
194634) work->b: ADDRESS: [0x14059b20] VALUE: [5.498979e-02]
194684) work->b: ADDRESS: [0x14059b20] VALUE: [9.323869e+07]
194689) work->b: ADDRESS: [0x14059b20] VALUE: [3.016410e+07]
194694) work->b: ADDRESS: [0x14059b20] VALUE: [1.688376e-08]
194699) work->b: ADDRESS: [0x14059b20] VALUE: [1.660441e+00]
.....

操作194699是在segfault之前得到的最后一组值;

Calling free_multifit...
194696) work->u: ADDRESS: [0x1305f7d0] VALUE: [1.350474e+01]
194697) work->w: ADDRESS: [0x92ec810] VALUE: [1.350474e+01]
194698) work->v: ADDRESS: [0x122cc210] VALUE: [5.798884e-09]
194699) work->b: ADDRESS: [0x14059b20] VALUE: [1.660441e+00]
194700) work->rv1: ADDRESS: [0xea37a50] VALUE: [0.000000e+00]
< If it didn't crash in the function we'd see an "Exiting function message" here - so it sigsegs on the freeing of one the the arrays or the work object itself.
[EOF]

所以,尽管检查指针是好的,并且实际从它的位置(1.66)中拉出一个值,但似乎当我尝试释放它时,一切都出错了。

任何想法为什么/如何发生?这是硬件问题吗?我在群集上运行它,如果这有任何区别。

更新1

通过以下方式创建multifit_work_t;

typedef struct {
  int m,n;
  double *w,*u,*v,*b,*rv1;
} multifit_work_t;


multifit_work_t *alloc_multifit(int m, int n)
{
  multifit_work_t *work=(multifit_work_t *)malloc(sizeof(multifit_work_t));
  if (work==NULL) {
    fprintf(stderr,"failed to allocate multifit_work\n");
    exit(1);
  }

  work->m=m;
  work->n=n;
  work->u=(double *)malloc(n*m*sizeof(double)); /* temporary storage - n x m matrix */
  work->w=(double *)malloc(n*sizeof(double)); /* n vector */
  work->v=(double *)malloc(n*n*sizeof(double)); /* n x n matrix */
  work->b=(double *)malloc(m*sizeof(double)); /* m vector */
  work->rv1=(double *)malloc(n*sizeof(double)); /* temporary storage - n vector */
  if (work->u==NULL || work->w==NULL || work->v==NULL || work->b==NULL || work->rv1==NULL) {
    fprintf(stderr,"failed to allocate multifit_work\n");
    exit(1);
  }

  return work;
}

更新2

当我在我的本地系统上运行时,会发生同样的事情,但错误就是这样;

 *** caught segfault ***
address 0x11e000000, cause 'memory not mapped'

始终处于明显均匀的内存地址。

更新3

以下是valgrind报告

valgrind --leak-check=full --show-reachable=yes ./execute 
==23072== Memcheck, a memory error detector
==23072== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==23072== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==23072== Command: ./execute
==23072== 
==23072== 
==23072== HEAP SUMMARY:
==23072==     in use at exit: 0 bytes in 0 blocks
==23072==   total heap usage: 445 allocs, 445 frees, 27,900 bytes allocated
==23072== 
==23072== All heap blocks were freed -- no leaks are possible
==23072== 
==23072== For counts of detected and suppressed errors, rerun with: -v
==23072== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 23 from 8)

这是在杀我!

3 个答案:

答案 0 :(得分:3)

你应养成在解放后将事情设置为NULL的习惯:

free(work->u);
free(work->w);
free(work->v);
free(work->b);
free(work->rv1);
work->u = work->w = work->v = work->b = work->rv1 = NULL;
free(work);

还在调用NULL的函数中将工作设置为free_multifit

答案 1 :(得分:2)

当您写入数组时,请确保您没有超越其范围。这些指针存储在堆中,因此我们可能会看到一些超出界限的指针损坏对数组的访问。

  

始终处于明显均匀的内存地址。

内存通常是字节对齐的,具体取决于操作系统和系统,并且您使用的是8字节值(64位双精度浮点数)。所以你可能会看到很多地址以0x .... 0,0x ...... 8,0x .... 10,0x ...... 18,0x ...... 20等结尾。

答案 2 :(得分:0)

在某些地方,深,深,在代码中,输入数组只填充本地数组(m)分配大小的一小部分。然后代码调用数组的未初始化区域,其值看起来很像预期的输入(这就是为什么我花了这么长时间来识别)。

总结一下 - 超越数组很糟糕,但也要注意重写(初始化时)!

相关问题