【问题标题】:Threading issue. debugging seg-fault线程问题。调试段错误
【发布时间】:2015-10-20 02:36:10
【问题描述】:

这是一个家庭作业问题。以下代码适用于单个线程,但是当多个线程运行此代码时,我会遇到 seg-faults。我一直在尝试使用 valgrind 和 gdb 进行调试,但我无法弄清楚。

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

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

【问题讨论】:

  • 这段代码在 Valgrind 下能以单线程模式干净地运行吗?
  • 请展示parse_line()的实现。
  • @user3088814 你能更新线程之间的共享内存访问吗?因为 seg-fault 会出现......当你访问的内存比你分配的更多时。
  • 是的,它在 valgrind 中以单线程模式运行干净。

标签: segmentation-fault pthreads


【解决方案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;
}

【讨论】:

  • 谢谢你,这是问题所在。
【解决方案2】:

我发现了问题。此代码调用 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;
}

【讨论】:

  • 此信息应该已通过编辑原始问题包含在内。我已经为代码做了这个。
猜你喜欢
  • 2016-03-23
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2015-11-08
  • 2011-03-31
  • 1970-01-01
  • 2017-12-20
  • 1970-01-01
相关资源
最近更新 更多