gpt4 book ai didi

c - 使用 pthreads 逐行读取文件...意外退出

转载 作者:太空宇宙 更新时间:2023-11-04 07:29:38 26 4
gpt4 key购买 nike

我有以下代码:

    /*//not important
FILE * INFILE;
list_file = optarg;
if( ( INFILE = fopen( list_file, "a+" ) ) == NULL ) {
fprintf( stderr, "Can't open input file\n");
exit(0);
}
*/

pthread_mutex_t input_queue;
pthread_mutex_init(&input_queue, NULL);

for( i = 0 ; i < number_thread; i++)
{
if( pthread_create( &thread_id[i], NULL, &work, NULL) != 0 )
{
i--;
fprintf(stderr, RED "\nError in creating thread\n" NONE);
}
}
for( i = 0 ; i < number_thread; i++)
if( pthread_join( thread_id[i], NULL) != 0 )
{
fprintf(stderr, RED "\nError in joining thread\n" NONE);
}




void * work(void * data)
{
unsigned long line;
char buf[512];
while ( !feof(INFILE) )
{
pthread_mutex_lock(&input_queue);
fgets((char *)&buf, sizeof(buf), INFILE);
if (buf[strlen (buf) - 1] == '\n')
buf[strlen (buf) - 1] = '\0';
line = (unsigned long)buf;
pthread_mutex_unlock(&input_queue);
do_work( line );
}
fclose(INFILE);
return NULL;
}

它从文件中读取行,但过了一会儿它意外退出,没有错误消息。我想我搞砸了什么。

我如何使用 pthreads 逐行读取文件,但尽可能保持代码不变(我的意思是不要弄乱整个程序)?

最佳答案

您正在关闭遇到 EOF 的第一个线程中的 INFILE。之后其他线程将在关闭的文件上调用 feof() — 并且可能调用 fclose() — 这将破坏堆并且几乎肯定会导致崩溃。此外,您的换行代码可能会在 EOF 处运行缓冲区不足,请参阅下面的备注。

要解决此问题,请使用相同的互斥锁保护 feof()fclose(),并将 INFILE 设置为 NULL。获取互斥量时,检查 INFILE 是否为 NULL,如果是则立即返回:

for (;;) {
pthread_mutex_lock(&input_queue);
if (!INFILE) {
pthread_mutex_unlock(&input_queue);
break;
}
if (feof(INFILE)) {
INFILE = NULL;
pthread_mutex_unlock(&input_queue);
break;
}

fgets(buf, sizeof(buf), INFILE);
pthread_mutex_unlock(&input_queue);

// ...strip newline, do_work...
}

几点说明:

  • 您的代码写入 buf[strlen(buf) - 1] 而不检查 strlen(buf) 是否为零。 buf 将在 EOF 处为空,因此这不是理论上的问题,它会在每次执行时恰好发生一次。

  • lineunsigned long 类型,但您正在为其分配一个指针值。这将在 long 不包含指针的平台上失败,例如 Win64。将 linedo_work 的参数声明为 char * (或者 void * 如果它必须接受其他指针类型)相反。

  • 避免将互斥体称为“队列”;在多线程编程队列中指的是producer-consumer aware FIFO .

  • 您不需要使用互斥锁保护单个 stdio 函数,例如 fgets。根据 POSIX 的规定,它们是 MT 安全的。 (但是,在我修改后的代码中,fgets() 确实需要受互斥锁保护,因为 INFILE 可能会在互斥锁未被持有时失效。)

  • (char *) &buf 没有意义。由于 buf 是一个 char 数组,它已经衰减为指向其第一个成员的指针,因此您只需将 buf 发送到 fgets 。如果您坚持使用地址运算符,正确的表达式是&buf[0]

  • 正如 Carl Norum 所暗示的,feof() 可能不是您想要的,因为它只检测 fgets() 已经遇到的 EOF 条件。检查 EOF 的正确方法是测试 fgets() 是否返回空字符串 — 在去除换行符之前

关于c - 使用 pthreads 逐行读取文件...意外退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15042527/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com