【问题标题】:Why does srand(time(NULL)) gives me segmentation fault on main?为什么 srand(time(NULL)) 给我主要的分段错误?
【发布时间】:2016-09-07 22:16:10
【问题描述】:

在这里需要一些帮助。

我想了解这段代码发生了什么。

我正在尝试将随机数作为tickets 生成到在ccreate 函数内部创建的TCP_t 结构。

问题是,每次我在没有 srand(time(NULL)) 的情况下执行此代码时,它都会一遍又一遍地返回相同的 "random" 数字序列,例如:

TID: 0 | TICKET : 103
TID: 1 | TICKET : 198

所以我用时间播种,生成真正的随机数。

当我将种子放入 newTicket 函数中时,它会在每次执行中带来不同的数字,但每个线程的数字相同。这是一个输出示例:

执行1:

TID: 0 | TICKET : 148
TID: 1 | TICKET : 148

执行 2:

TID: 0 | TICKET : 96
TID: 1 | TICKET : 96

所以,经过一番研究,我发现我不应该每次调用 rand 时都播种它,而只能在程序开始时播种一次。现在,将种子放入 main 函数后,它给了我分段错误,我不知道为什么。

这可能是一个愚蠢的问题,但我真的很想了解发生了什么。

不知何故,种子在搞什么鬼? 我错过了什么吗? 我应该以另一种方式生成随机数吗?

#include <ucontext.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define MAX_TICKET 255
#define STACK_SIZE 32000

typedef struct s_TCB {
  int threadId;
  int ticket;
  ucontext_t context;
} TCB_t;

void test();
int newTicket();
int newThreadId();
int ccreate (void* (*start)(void*), void *arg);
int threadId = 0;

int main(){
  srand(time(NULL)); //<<<============== HERE = SEGMENTATION FAULT
  ccreate((void*)&test, 0);
  ccreate((void*)&test, 0);
}

int ccreate (void* (*start)(void*), void *arg){
    if(start == NULL) return -1;

    ucontext_t threadContext;
    getcontext(&threadContext);
    makecontext(&threadContext, (void*)start, 0);
    threadContext.uc_stack.ss_sp = malloc(STACK_SIZE);
    threadContext.uc_stack.ss_size = STACK_SIZE;

    TCB_t * newThread = malloc(sizeof(TCB_t));
    if (newThread == NULL) return -1;

    int threadThreadId = newThreadId();
    newThread->threadId = threadThreadId;
    newThread->ticket = newTicket();

    printf("TID: %d | TICKET : %d\n", newThread->threadId, newThread->ticket);

    return threadThreadId;
}

int newThreadId(){
  int newThreadId = threadId;
  threadId++;
  return newThreadId;
}

int newTicket(){
  //srand(time(NULL)); //<<<============== HERE = IT PARTIALLY WORKS
  return (rand() % (MAX_TICKET+1));
}

void test(){
  printf("this is a test function");
}

感谢所有帮助我的人。

如果代码太难看,很抱歉。尽量简化它。

【问题讨论】:

  • 只是OOC,你为什么连续两次用相同的参数调用ccreate?您是否 100% 确定 seg 错误实际上是在 seeds 的线路上?
  • ccreate((void*)&amp;test, 0); 没有理由在这里投。
  • 我没有ucontext.h,所以我不得不删除所有的ccreate,但我没有seg vault。您确定 srand 是问题所在吗?你能举一个更小的例子吗? (stackoverflow.com/help/mcve)
  • ccreate((void*)&amp;test, 0); 更有可能导致段错误,但它被误报为在 srand 线上

标签: c random time srand ucontext


【解决方案1】:

问题不在于srand(time(NULL)),而在于makecontext。
您可以通过 sanatizer 运行您的代码以确认:

gcc-6 -fsanitize=undefined -fsanitize=address -fsanitize=leak -fsanitize-recover=all -fuse-ld=gold -o main main.c
./main 
ASAN:DEADLYSIGNAL
=================================================================
==8841==ERROR: AddressSanitizer: SEGV on unknown address 0x7fc342ade618 (pc 0x7fc340aad235 bp 0x7ffd1b945950 sp 0x7ffd1b9454f8 T0)
    #0 0x7fc340aad234 in makecontext (/lib/x86_64-linux-gnu/libc.so.6+0x47234)
    #1 0x400d2f in ccreate (/home/malko/Desktop/main+0x400d2f)
    #2 0x400c19 in main (/home/malko/Desktop/main+0x400c19)
    #3 0x7fc340a87f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #4 0x400b28  (/home/malko/Desktop/main+0x400b28)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0x47234) in makecontext
==8841==ABORTING

您可以通过设置堆栈大小在创建上下文来解决问题:

char stack[20000];
threadContext.uc_stack.ss_sp = stack;
threadContext.uc_stack.ss_size = sizeof(stack);
makecontext(&threadContext, (void*)start, 0);

无关,但请确保您还在示例代码中释放了 malloc 的内存。

【讨论】:

    猜你喜欢
    • 2020-07-25
    • 1970-01-01
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    相关资源
    最近更新 更多