C多进程程序通过shell重定向文件输入时输出乱码问题
问题根因分析
- 核心原因:C标准库
stdin默认采用全缓冲模式,父子进程的用户态缓冲区独立
你通过管道将两个输入文件的内容合并传给程序时,第一个拿到互斥锁的进程(通常是父进程)调用scanf读前5个值时,C标准库会一次性把管道内所有可用数据全部读到自己进程的用户态stdin缓冲区中,不会只读刚好5个int对应的数据。
而fork()生成的子进程拥有独立的地址空间,父进程缓冲区里剩下的输入内容(也就是input2.txt的内容)无法被子进程访问到,子进程调用scanf时读不到有效输入,scanf执行失败,未初始化的栈变量value的随机垃圾值就被写到了输出文件中,也就是你看到的乱码负数。
互斥锁仅能保证两个进程不会同时执行读写逻辑,无法解决用户态缓冲跨进程不可见的问题。 - 次要bug:互斥锁销毁逻辑错误
你初始化的是存在共享内存里的shared_mutex,但程序末尾销毁的是从未初始化过的全局变量mutex,会触发未定义行为。
修复方案
- 禁用
stdin的用户态缓冲,让每次读取直接从内核管道获取数据,内核态的管道数据是所有进程共享的。在main函数最开头加入以下代码:
setvbuf(stdin, NULL, _IONBF, 0);
- 修正互斥锁销毁逻辑,改为销毁
shared_mutex:
// 原错误代码 pthread_mutex_destroy(&mutex); pthread_mutex_destroy(shared_mutex);
- 可选:增加
scanf返回值判断,避免读取失败时写入垃圾值:
for (int i = 0; i < n; ++i) { if (scanf("%d", &value) != 1) { perror("read input failed"); break; } fprintf(file, "%d ", value); }
内容的提问来源于stack exchange,提问作者Ildar
相关产品推荐
相关产品推荐

