4

私は途方に暮れています。この些細なコードで Segfault が発生します。何が間違っている可能性がありますか??

struct  random_data *qq;

qq = calloc(50, sizeof(struct random_data));
srandom_r(time(NULL), qq);

これを次のように変更すると、機能します。

struct  random_data qq;

srandom_r(time(NULL), &qq);

私は完全なバカに違いないのですが、それを理解することはできません。助けてください。

更新: calloc は有効なポインタを返します

(uint64_t) 1aa5010

ただし、 &qq はポインタを表します

(uint64_t) 7fffbb428090

それが違いですが、srandom_r が実行に失敗する理由は不明です。Linux 2.6.32-44-server #98-Ubuntu で試す

4

3 に答える 3

5

ほとんどの回答が実際にコードを実行しようとしたことがないようです。これは非常に最小限のプログラムであり、実際に問題を示しています。

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main() {
 int seed = time(NULL);
 struct random_data *qq = NULL;

 qq = calloc(1, sizeof(struct random_data));
 if(qq) {
   srandom_r(seed, qq); /* segfault! */
 } else {
   printf("failed to allocate `qq`\n");
 }
 return 0;
}

valgrind は、不正なメモリ アクセス以外はほとんど表示されません。

==22907== サイズ 4 の無効な書き込み ==22907== at 0x409CE8D: srandom_r (random_r.c:182) ==22907== by 0x80484A1: main (srand_ko.c:10) ==22907== アドレス 0x0 はstack'd、malloc'd、または (最近) free'd ではない

構造体を見るとrandom_data、状態バッファへのポインタが含まれていることがわかります。

struct random_data
  {
    int32_t *fptr;              /* Front pointer.  */
    int32_t *rptr;              /* Rear pointer.  */
    int32_t *state;             /* Array of state values.  */
    int rand_type;              /* Type of random number generator.  */
    int rand_deg;               /* Degree of random number generator.  */
    int rand_sep;               /* Distance between front and rear.  */
    int32_t *end_ptr;           /* Pointer behind state table.  */
  };

で割り当てた場合、これらのポインターはすべて NULL になることは明らかでありcalloc()、それsrandom_rはあまり好きではありません。random_data状態値の配列を手動で割り当て、を使用して構造体に割り当てることができますinitstate_r。はinitstate_rすでに を受け取っているので、もうseed呼び出す必要はありsrandom_rません (ただし、必要に応じて呼び出すことができます):

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define STATESIZE 64
int main() {
 int seed = time(NULL);
 char*buf = (char*)calloc(STATESIZE, sizeof(char));
 struct random_data *qq = NULL;

 qq = calloc(1, sizeof(struct random_data));
 initstate_r(seed, buf, STATESIZE, qq);
 /* generate some random numbers */
 /* ... */

 srandom_r(seed, qq);
 /* generate the same random numbers again */
 /* ... */

 /* cleanup */
 free(buf);
 free(qq);
 return 0;
}
于 2013-09-02T12:53:40.610 に答える
1

合格するとセグメンテーション違反が発生する可能性が最も高いためcalloc()、成功したかどうかのテストを追加したくない場合があります。NULL

#include <stdlib.h>

...

  struct random_data * qq = calloc(50, sizeof(*qq));
  if (NULL == qq)
    perror("malloc() failed");
  else
    srandom_r(time(NULL), qq);
于 2013-09-02T09:21:38.170 に答える