segfault在srandom_r

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上尝试

uml*_*ute 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;
}
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)