0

R関数内に埋め込まれたCコードがいくつかありますが、これは同じ方法でシグセグを続けますが、異なるポイントで(プログラムの進行を通じて-常に同じ関数から来ているようです)。

これが問題です-私が得るエラーは次のとおりです。

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

現在、これはかなり標準的なエラーです (私munmap_chunk()free()思い出せば正常に動作する過程)。

関数は次のようになります。

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 すると、多くのヒットが得られます (当然のことながら、解放された後に同じメモリ位置を再利用しています)。

$: 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)

これは私を殺している !

4

3 に答える 3

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また、 を呼び出す関数でwork を設定しますfree_multifit

于 2012-06-01T14:59:41.703 に答える
2

配列に書き込むときは、配列の境界を超えていないことを確認してください。これらのポインターはヒープに格納されているため、配列への範囲外アクセスによるポインターの破損が発生している可能性があります。

常に著しく偶数のメモリアドレスにあります。

メモリは通常、OSとシステムに応じてバイト整列され、8バイト値(64ビット倍精度浮動小数点数)で作業しています。したがって、0x .... 0、0x .... 8、0x .... 10、0x .... 18、0x....20などで終わるアドレスがたくさん表示される可能性があります。

于 2012-06-01T19:16:48.083 に答える
0

コードのどこか、深いところ、入力配列はローカル配列に割り当てられた (m) 割り当てられたサイズのごく一部しか満たしていませんでした。次に、コードは配列の初期化されていない領域を呼び出していました。その値は、予想される入力とよく似ていました (これが、特定するのに非常に長い時間がかかった理由です)。

要約すると、配列のオーバーステッピングは良くありませんが、アンダーステッピング (初期化時) にも注意してください!

于 2012-06-07T19:02:29.093 に答える