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