2016-09-07 5 views
2

도움이 필요합니다.srand (time (NULL))이 main에서 세그먼트 화 오류를 발생시키는 이유는 무엇입니까?

이 코드에서 무슨 일이 일어나고 있는지 알고 싶습니다.

ccreate 내부에 생성 된 TCP_t 구조체에 난수를 tickets으로 생성하려고합니다.

문제는 매번 내가 예를 들어,이 번호 반복 "무작위" 같은 순서를 반환 srand(time(NULL))없이이 코드를 실행한다 :

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"); 
} 

나에게 손을 빌려준 사람 덕분입니다.

그리고 코드가 너무 추해 읽을 수없는 경우 죄송합니다. 내가 할 수있는만큼 그것을 단순화하려고 노력했다.

+2

그냥 OOC, 같은 인자를 사용하여'ccreate'를 두 번 연속 호출하는 이유는 무엇입니까? seg 오류가 실제로 '시드'라는 줄에 100 % 확실합니까? – ShadowRanger

+1

'ccreate ((void *) & test, 0);'여기에 캐스팅 할 이유가 없습니다. – wildplasser

+0

'ucontext.h'가 없으므로 ccreate를 모두 제거해야했지만 seg 저장고를 얻지 못했습니다. srand가 문제라고 확신합니까? 더 작은 예제를 만들 수 있습니까?(http://stackoverflow.com/help/mcve) – Riley

답변

4

문제는 srand(time(NULL))이 아닌 makecontext입니다.

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 

당신은 컨텍스트 만들기 전에 스택 크기 를 설정하여 문제를 해결할 수 있습니다 :
당신은 확인하기 위해 sanatizer를 통해 코드를 실행할 수 있습니다

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

는 관련없는,하지만 샘플 코드에서 malloc 된 메모리를 해제해야합니다.