这是一个家庭工作问题。以下代码适用于单个线程,但是当多个线程运行时,我会遇到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);
}
答案 0 :(得分:1)
你的问题是strtok()
不能同时从几个线程中使用,因为它使用静态内部状态(它不是可重入的)。
POSIX包含名为strtok()
的{{1}}的可重入变体 - 您应该使用此代码:
strtok_r()
答案 1 :(得分: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;
}