2015-10-20 39 views
0

这是一个家庭工作问题。下面的代码对单个线程正常工作,但是当多个线程运行这个时,我得到了seg-faults。我一直在尝试使用valgrind和gdb进行调试,但我无法弄清楚。线程问题。调试seg-fault

您是否在此线程中看到任何会导致问题的内容?

static int parse_line(char *line, const char *delim, char *field[]) 
{ 
    char *next; 
    int cnt = 0; 

    next = strtok(line, delim); 
    while (next) { 
    if (cnt == MAX_NUM_FIELDS - 1) 
    break; 
    field[cnt] = (char *) malloc(strlen(next) + 1); 
    strcpy(field[cnt++], next); 
    next = strtok(NULL, delim); 
    } 
    field[cnt] = (char *) 0; /* make the field array be null-terminated */ 
    int i; 
    for (i = 0; i < cnt; i++) { 
    free(field[cnt]); 
    } 
    return cnt; 
} 

void *process_file(void *ptr) 
{ 
    char *filename = (char *) ptr; 
    char *linebuffer = (char *) malloc(sizeof(char) * MAX_LINE_SIZE); 
    char **field = (char **) malloc(sizeof(char *) * MAX_NUM_FIELDS); 
    char *end_date = (char *) malloc(sizeof(char) * MAX_LINE_SIZE); 

    fprintf(stderr, "%s: processing log file %s\n", program_name, 
     filename); 
    FILE *fin = fopen(filename, "r"); 
    if (fin == NULL) { 
    fprintf(stderr, "Cannot open file %s\n", filename); 
    pthread_exit(1); 
    } 
    char *s = fgets(linebuffer, MAX_LINE_SIZE, fin); 
    if (s != NULL) { 
    int num = parse_line(linebuffer, " []\"", field); 
    update_webstats(num, field); 
    printf("Starting date: %s\n", field[3]); 
    free_tokens(num, field); 

    while (fgets(linebuffer, MAX_LINE_SIZE, fin) != NULL) { 
     int num = parse_line(linebuffer, " []\"", field); 
     strcpy(end_date, field[3]); 
     update_webstats(num, field); 
     free_tokens(num, field); 
     strcpy(linebuffer, ""); 
    } 
    printf("Ending date: %s\n", end_date); 

    } 
    free(end_date); 
    free(field); 
    free(linebuffer); 
    fclose(fin); 
    pthread_exit(NULL); 
} 
+0

在单线程模式不干净下Valgrind的这段代码运行? –

+0

请显示'parse_line()'的实现。 – caf

+0

@ user3088814可以更新线程之间的共享内存访问吗?因为seg-fault会来......当你访问更多的内存比你分配。 – Mohan

回答

0

我发现了这个问题。此代码调用strtok,这不是线程安全的。应该strtokk_r

static int parse_line(char *line, const char *delim, char *field[]) 
{ 
    char *next; 
    int cnt = 0; 

    next = strtok(line, delim); 
    while (next) { 
    if (cnt == MAX_NUM_FIELDS - 1) 
    break; 
    field[cnt] = (char *) malloc(strlen(next) + 1); 
    strcpy(field[cnt++], next); 
    next = strtok(NULL, delim); 
    } 
    field[cnt] = (char *) 0; /* make the field array be null-terminated */ 
    int i; 
    for (i = 0; i < cnt; i++) { 
    free(field[cnt]); 
    } 
    return cnt; 
} 
+0

通过编辑原始问题应包含此信息。我为代码做了这个。 – caf

1

您的问题是strtok()不能同时从多个线程中使用,因为它使用静态的内部状态(这是不可重入)。

POSIX包括strtok()重入变种,叫strtok_r() - 你应该使用这样的:

static int parse_line(char *line, const char *delim, char *field[]) 
{ 
    char *next; 
    int cnt = 0; 
    char *saveptr; 

    next = strtok_r(line, delim, &saveptr); 
    while (next) { 
     if (cnt == MAX_NUM_FIELDS - 1) 
      break; 
     field[cnt] = (char *) malloc(strlen(next) + 1); 
     strcpy(field[cnt++], next); 
     next = strtok_r(NULL, delim, &saveptr); 
    } 
    field[cnt] = (char *) 0; /* make the field array be null-terminated */ 
    int i; 
    for (i = 0; i < cnt; i++) { 
     free(field[cnt]); 
    } 
    return cnt; 
} 
+0

谢谢你是这个问题。 – user3088814