3

이 코드는 10 개의 파일 이름을 가진 입력 파일을 받고 2 차원 배열에 저장하고 10 + 1 스레드를 생성합니다 : 요청자와 10 개의 변환기. 이것은 단지 뼈대 일 뿐이므로 내 스레드는 자신의 ID 만 인쇄합니다. 전역 변수 나 공유 변수 또는 뮤텍스가 필요한 항목에는 액세스하지 않습니다. 그렇다면 여기서 세분화 오류를 방지하려면 어떻게해야합니까?pthread_join이 세그먼테이션 결함으로 연결됩니다. 왜?

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <semaphore.h> 
#include <string.h> 
#include <time.h> 
#include <sys/wait.h> 
#include <sys/types.h> 
#include <sys/time.h> 
#include <math.h> 
#include <unistd.h> 
#include <errno.h> 

#define READ_BUFFER_LEN 16 
//#define MAX_LENGTH 128 

enum { 
    MAX_LENGTH = 512 
}; 

typedef struct FileNameArray { 
    size_t nfiles; /* Number of file names allocated and in use */ 
    size_t maxfiles; /* Number of entries allocated in array */ 
    char **files; /* Array of file names */ 
} FileNameArray; 


//GLOBAL vars 
int num_images, *threads_ids /*threads ids*/; 
pthread_t *threads; 

void deallocate2D(FileNameArray *names) { 
    size_t i; 
    for (i = 0; i < names->nfiles; i++) 
     free(names->files[i]); 
    free(names->files); 
    names->nfiles = 0; 
    names->files = 0; 
    names->maxfiles = 0; 
} 

int readInputFile(FILE *fp, FileNameArray *names) { 
    num_images = names->nfiles; 
    int max_lines = names->maxfiles; 
    char **file_names = names->files; 
    char line[MAX_LENGTH]; 
    char **final_filenames, **array; 

    while (fgets(line, sizeof line, fp) != NULL) { 
     if (line[0] != '\n') { 
      /* Remove newline from end of file name */ 
      char *nl = strchr(line, '\n'); 
      if (nl != 0) 
       *nl = '\0'; 
      if (num_images >= max_lines) { 
       max_lines += 100; 
       array = realloc(file_names, max_lines * sizeof (char*)); 
       if (array == NULL) { 
        fprintf(stderr, "Error reallocating space for 2d array: %s\n", 
          strerror(errno)); 
        return -1; 
       } 
       names->maxfiles = max_lines; 
       names->files = array; 
       file_names = array; 
      } 
      if ((file_names[num_images] = malloc(strlen(line) + 1)) == NULL) { 
       fprintf(stderr, "Error allocating space for 2d array: %s\n", 
         strerror(errno)); 
       return -1; 
      } 
      names->nfiles++; 
      strcpy(file_names[num_images], line); 
      printf("name of file %d is: %s \n", num_images, file_names[num_images]); 
      num_images++; 
     } 
    } 

    printf("Num_lines: %d\n", num_images); 
    //realloc to number of lines in the file, to avoid wasting memory 
    if ((final_filenames = realloc(file_names, num_images * sizeof (char*))) == NULL) { 
     fprintf(stderr, "Error reallocating space for 2d array: %s\n", 
       strerror(errno)); 
     return -1; 
    } 
    names->maxfiles = num_images; 
    names->files = final_filenames; 
    return 0; 
} 

void* requester(void* arg) { 

    printf("This is the requester thread\n"); 
    //sleep(1); 
    pthread_exit(NULL); 
    return NULL; 
} 

void* converter(void *id) { 
    int my_id = *((int*) id); 

    printf("Thread's id is: %d\n", my_id); 
    pthread_exit(NULL); 
    return NULL; 
} 

int main(int argc, char *argv[]) { 
    FileNameArray names = {0, 0, 0}; 
    int i, rc; 
    pthread_attr_t attr; 


    //check parameters 
    if (argc < 4) { 
     fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n", 
       argv[0]); 
     return -1; 
    } 

    printf("Opening input file [%s]\n", argv[1]); 
    FILE *fpin = fopen(argv[1], "r"); 
    if (fpin == NULL) { 
     fprintf(stderr, "Could not open input file %s (%s)\n", 
       argv[1], strerror(errno)); 
     return -1; 
    } 

    if ((names.files = malloc(10 * sizeof (char*))) == NULL) { 
     fprintf(stderr, "Error allocating initial space for 2d array: %s\n", 
       strerror(errno)); 
     return -1; 
    } 
    names.maxfiles = 10; 

    if (readInputFile(fpin, &names) == -1) { 
     fprintf(stderr, "Error reading image filenames from input\n"); 
     return -1; 
    } 

    threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t)); 
    threads_ids = (int*) malloc(num_images + 1 * sizeof (int)); 

    /* Initialize and set thread detached attribute */ 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    //creates requester thread, the 1st one on the list 
    pthread_create(&threads[0], &attr, requester, &threads_ids[0]); 
    threads_ids[0] = 0; 

    //creates so many converter threads as the number of images to convert 
    for (i = 1; i < num_images + 1; i++) { 
     threads_ids[i] = i; 
     rc = pthread_create(&threads[i], &attr, converter, &threads_ids[i]); 
     if (rc) { 
      printf("ERROR; return code from pthread_create() is %d\n", rc); 
      exit(-1); 
     } 
    } 


    /* Free attribute and wait for the other threads */ 
    pthread_attr_destroy(&attr); 

    for (i = 0; i < num_images + 1; i++) { 
     printf("Waiting for thread nr %d\n", i); 
     rc = pthread_join(threads[i], NULL); 
     if (rc) { 
      printf("ERROR; return code from pthread_join() is %d\n", rc); 
      exit(-1); 
     } 
    } 

    fclose(fpin); 
    free(threads); 
    free(threads_ids); 
    printf("###########\n"); 

    deallocate2D(&names); 

    printf("Done!\n"); 
    return 0; 
} 

이 가능한으로 출력한다 중 하나입니다

Num_lines: 10 
This is the requester thread 
Thread's id is: 1 
Thread's id is: 2 
Thread's id is: 3 
Thread's id is: 5 
Thread's id is: 4 
Thread's id is: 6 
Thread's id is: 7 
Thread's id is: 8 
Thread's id is: 9 
Waiting for thread nr 0 
Thread's id is: 10 
Segmentation fault 

이것은 GDB의 결과입니다 : 물론

Program received signal SIGSEGV, Segmentation fault. 
0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724 
3724 malloc.c: No such file or directory. 
    in malloc.c 
(gdb) where 
#0 0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724 
#1 0x00120802 in *__GI__dl_deallocate_tls (tcb=<value optimized out>, 
    dealloc_tcb=112) at dl-tls.c:487 
#2 0x00133748 in __free_stacks (limit=41943040) at allocatestack.c:274 
#3 0x00133849 in queue_stack (pd=0xb5fd9b70) at allocatestack.c:302 
#4 __deallocate_stack (pd=0xb5fd9b70) at allocatestack.c:740 
#5 0x00134b37 in pthread_join (threadid=3053296496, thread_return=0x0) 
    at pthread_join.c:110 
#6 0x0804955c in main (argc=4, argv=0xbffff4a4) at main.c:261 
+0

main.c의 26 번째 줄은 어디입니까? –

+0

26이 아닌 261 행은 다음과 같습니다. rc = pthread_join (threads [i], NULL); – neverMind

답변

8
threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t)); 
threads_ids = (int*) malloc(num_images + 1 * sizeof (int)); 

당신이 구성되어 있어야합니다

쓰기 16,
threads = malloc((num_images + 1) * sizeof (pthread_t)); 
threads_ids = malloc((num_images + 1) * sizeof (int)); 

또는

threads = calloc(num_images + 1, sizeof (pthread_t)); 
threads_ids = calloc(num_images + 1, sizeof (int)); 

대신?

+1

LO, omg 이것은 단지 양육의 문제였습니까? – neverMind

+0

@neverMind : 네, 부분적으로 변수가 너무 작습니다. 곱셈과 나눗셈은 정규 수학과 마찬가지로 항상 더하기와 빼기 전에 발생합니다. 순서를 변경해야하는 경우 괄호를 추가해야합니다. –

+3

또한,'malloc'의 결과를 캐스팅하지 마십시오. 이렇게하면 컴파일러가'#include'd stdlib.h 파일을 제대로 찾지 못하게됩니다. 암시 적 캐스트가 발생하고 표준 및 관용적 인 C가됩니다. –

관련 문제