it seems like most answers never actually tried to run your code. here's a very minimalistic program, that indeed exhibits your problem:
#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 doesn't show much apart from an illegal memory access:
==22907== Invalid write of size 4 ==22907== at 0x409CE8D: srandom_r (random_r.c:182) ==22907== by 0x80484A1: main (srand_ko.c:10) ==22907== Address 0x0 is not stack'd, malloc'd or (recently) free'd
now when looking at the random_data
struct, you will find that it contains a pointer to a state-buffer:
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. */
};
obviously all those pointers will be NULL if you allocate with calloc()
, and srandom_r
doesn't really like that.
you can help it be manually allocating an array of state values and assign it to the random_data
struct using initstate_r
.
since initstate_r
already takes a seed
, you don't need to call srandom_r
anymore (but you can if you want to):
#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;
}