我的智慧结束了。这个简单的代码给了我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
答案 0 :(得分: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 ==在0x409CE8D:srandom_r(random_r.c:182) == 22907 == by 0x80484A1:main(srand_ko.c:10) == 22907 ==地址0x0未堆叠,malloc'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. */
};
如果你使用calloc()
进行分配,那么所有这些指针显然都是NULL,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;
}
答案 1 :(得分: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);
答案 2 :(得分:1)
'random_data'不包含保存随机数生成器状态的内存-它保存状态为...的状态。
使用random_r的“正确方法”是:
struct random_data rstate;
char random_bin[256];
initstate_r(MY_SEED,random_bin,256,&rstate);
现在您可以调用srandom_r和random_r。
不需要进行任何malloc或calloc的操作,这样做会减慢您的速度,因为每次您生成随机数时都会遇到高速缓存未命中的情况。