我正在从事一个编程项目,以更好地理解线程之间的同步。我逐行解析文本文件(使用多线程)以读取网站名称 (stackoverflow.com) 并将此名称排入我实现的 FIFO 数据结构中。一旦队列有名称要解析,多个线程就会开始将这些名称从队列中取出并将名称解析为 IP 地址。我使用这篇文章的最佳答案作为逐行阅读的模型。
由于使用了
if (line) free(line);
,所以这个最佳答案有点争议我已经使用valgrind将我的问题追溯到对free()
的调用。
这里是链接帖子中描述的逐行读取文件的方法:
void *service_file(void *arguments)
{
req_arg_struct *args = arguments;
FILE *data_file;
char *line = NULL;
size_t len = 0;
ssize_t read;
// code omitted to open next data_file in queue
while ((read = getline(&line, &len, data_file)) != -1)
{
if (read <= MAX_NAME_LENGTH)
{
en_q(args->shared_array, line);
fprintf(args->req_log, "Added %s for resolution\n", line);
}
}
fclose(data_file);
// get next file and repeat
}
/*
Removing the call to free below will completely resolve the problem,
but results in memory leak as found using valgrind
*/
if (line)
free(line);
pthread_exit(NULL);
}
其他主题:
void *resolve_addr(void *arguments)
{
res_arg_struct *args = arguments;
// code omitted to get next address to resolve
{
char ip_addr[MAX_IP_LENGTH];
// the function below resolves curr_address to ip_addr
int lookup_res = dnslookup(curr_address, ip_addr, MAX_IP_LENGTH);
if (lookup_res == 0) // no errors in dnslookup
{
fprintf(args->res_log, "%s, %s\n", curr_address, ip_addr); // curr_address prints
}
else // something went wrong, likely curr_address wasn't readable
{
fprintf(args->res_log, "%s, NOT_RESOLVED\n", curr_address); // curr_address prints as empty string
}
// get next address and continue
}
pthread_exit(NULL);
}
请记住,这些函数作为参数传递给对
pthread_create()
的调用,并且多个线程正在执行上面显示的代码。 FIFO 队列使用信号量进行保护,我已经能够验证这种保护是有效的。在上面的代码上运行 valgrind 会导致许多错误,如下所示:
==21891== Invalid read of size 1
==21891== at 0x50A5CD0: vfprintf (vfprintf.c:1632)
==21891== by 0x50AC806: fprintf (fprintf.c:32)
==21891== by 0x40102A: resolve_addr (multi-lookup.c:84)
==21891== by 0x4E416B9: start_thread (pthread_create.c:333)
==21891== Address 0x5428280 is 0 bytes inside a block of size 120 free'd
==21891== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21891== by 0x400F7E: service_file (multi-lookup.c:61)
==21891== by 0x4E416B9: start_thread (pthread_create.c:333)
==21891== Block was alloc'd at
==21891== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21891== by 0x50C59F7: getdelim (iogetdelim.c:62)
==21891== by 0x400EFF: service_file (multi-lookup.c:29)
==21891== by 0x4E416B9: start_thread (pthread_create.c:333)
但达到:
==21891== HEAP SUMMARY:
==21891== in use at exit: 0 bytes in 0 blocks
==21891== total heap usage: 1,676 allocs, 1,676 frees, 9,681,222 bytes allocated
==21891==
==21891== All heap blocks were freed -- no leaks are possible
现在,如果我删除对
free(line)
的调用,代码将按预期工作(fprintf
适当地写入包含在 line
中的主机名),但是 valgrind 显示:
==21938== HEAP SUMMARY:
==21938== in use at exit: 600 bytes in 5 blocks
==21938== total heap usage: 1,550 allocs, 1,545 frees, 9,476,382 bytes allocated
==21938==
==21938== 600 bytes in 5 blocks are definitely lost in loss record 1 of 1
==21938== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21938== by 0x50C59F7: getdelim (iogetdelim.c:62)
==21938== by 0x400EFF: service_file (multi-lookup.c:29)
==21938== by 0x4E416B9: start_thread (pthread_create.c:333)
==21938==
==21938== LEAK SUMMARY:
==21938== definitely lost: 600 bytes in 5 blocks
==21938== indirectly lost: 0 bytes in 0 blocks
==21938== possibly lost: 0 bytes in 0 blocks
==21938== still reachable: 0 bytes in 0 blocks
==21938== suppressed: 0 bytes in 0 blocks
为什么我释放
fprintf
时调用line
会出现无效读取?