4

我无计可施。这个微不足道的代码给了我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

4

3 回答 3

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== 由 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.  */
  };

显然,如果您使用 分配,所有这些指针都将为 NULL calloc(),并且srandom_r并不真正喜欢那样。您可以帮助它手动分配状态值数组并将其分配给random_data使用initstate_r. 因为initstate_r已经需要 a 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;
}
于 2013-09-02T12:53:40.610 回答
2

'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 任何东西,这样做会减慢您的速度,因为每次生成随机数时都会出现缓存未命中。

于 2019-12-08T02:22:29.770 回答
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);
于 2013-09-02T09:21:38.170 回答