wic*_*ick 4 c linux random reentrancy
我机智。这个琐碎的代码给了我Segfault,可能是什么错误?
struct random_data *qq;
qq = calloc(50, sizeof(struct random_data));
srandom_r(time(NULL), qq);
Run Code Online (Sandbox Code Playgroud)
现在,如果我像这样更改它,它将起作用:
struct random_data qq;
srandom_r(time(NULL), &qq);
Run Code Online (Sandbox Code Playgroud)
我一定是个笨蛋,但我无法把握。请帮忙。
更新:calloc返回有效的指针
(uint64_t) 1aa5010
Run Code Online (Sandbox Code Playgroud)
但是,&qq代表指针
(uint64_t) 7fffbb428090
Run Code Online (Sandbox Code Playgroud)
就是这样,但是还不清楚为什么srandom_r无法执行。我在Linux 2.6.32-44-服务器#98-Ubuntu上尝试
似乎大多数答案从未真正尝试过运行您的代码。这是一个非常简单的程序,确实显示了您的问题:
#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;
}
Run Code Online (Sandbox Code Playgroud)
valgrind除了显示非法的内存访问外,没有其他显示:
== 22907 ==大小为4的无效写入== 22907 ==在0x409CE8D:srandom_r(random_r.c:182)== 22907 ==由0x80484A1:main(srand_ko.c:10)== 22907 ==地址0x0为没有堆栈,malloc或(最近)释放
现在,当查看该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. */
};
Run Code Online (Sandbox Code Playgroud)
显然,如果您使用进行分配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;
}
Run Code Online (Sandbox Code Playgroud)