I'm at my wits end. This trivial code gives me Segfault, what could be possibly wrong??
struct random_data *qq;
qq = calloc(50, sizeof(struct random_data));
srandom_r(time(NULL), qq);
Now if I change it like this, it works:
struct random_data qq;
srandom_r(time(NULL), &qq);
I must be a total moron, but I can't grasp it. Please, help.
Update: calloc returns a valid pointer
(uint64_t) 1aa5010
However, &qq represents the pointer
(uint64_t) 7fffbb428090
and that's the difference, but it's unclear why srandom_r fails to execute. I try at Linux 2.6.32-44-server #98-Ubuntu
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With