我只是不得不追踪一个非常烦人的bug,有人使用popen打开管道,但用fclose而不是pclose关闭C文件。在Linux上,这是没有问题的,但后来这个程序在OSX上编译,事情就变了。所以我想知道,当用fclose而不是pclose关闭由popen创建的管道时,会出现什么问题?为什么这在Linux上有效,而不是OSX/BSD?
popen
fclose
pclose
mcvgt66p1#
它可能只是 * 看起来 * 与Linux一起工作,例如,您没有注意到这个问题。这些问题列出了在需要pclose的情况下使用fclose时程序可能出现故障的几种方式(在各种平台上):
那些有几个关于不正确关闭管道可能发生的坏事情(例如,zombie processes)的注解。在某些情况下,你的程序可能打开一个管道 * 一次 *,然后第二次打开管道失败。
brgchamk2#
我不知道你认为这些问题会得到什么样的答案,但是...所以我想知道,当用fclose而不是pclose关闭由popen创建的管道时,会出现什么问题?问题是程序员没有遵守popen API的设计契约。这导致了未定义的行为。您得到的行为是一个实现细节。从字面上讲,除非通过分析您正在使用的C库的实现,否则您无法知道可能出错的地方。为什么这在Linux上工作,而不是OSX/BSD?因为未定义的行为可以包括fclose在popen返回的文件指针上像pclose一样工作。或者它可以包括它不以你观察到的任何方式工作。而且因为实现在无数方面不同。
bvpmtnay3#
我认为最安全的方法是:
if( lseek(fileno(fp), (off_t) 0, SEEK_SET) < 0 ) pclose(fp); else fclose(fp);
字符串我不明白为什么库不直接用这种方式实现fclose。
3条答案
按热度按时间mcvgt66p1#
它可能只是 * 看起来 * 与Linux一起工作,例如,您没有注意到这个问题。这些问题列出了在需要
pclose
的情况下使用fclose
时程序可能出现故障的几种方式(在各种平台上):那些有几个关于不正确关闭管道可能发生的坏事情(例如,zombie processes)的注解。在某些情况下,你的程序可能打开一个管道 * 一次 *,然后第二次打开管道失败。
brgchamk2#
我不知道你认为这些问题会得到什么样的答案,但是...
所以我想知道,当用
fclose
而不是pclose
关闭由popen
创建的管道时,会出现什么问题?问题是程序员没有遵守
popen
API的设计契约。这导致了未定义的行为。您得到的行为是一个实现细节。从字面上讲,除非通过分析您正在使用的C库的实现,否则您无法知道可能出错的地方。为什么这在Linux上工作,而不是OSX/BSD?
因为未定义的行为可以包括
fclose
在popen
返回的文件指针上像pclose
一样工作。或者它可以包括它不以你观察到的任何方式工作。而且因为实现在无数方面不同。bvpmtnay3#
我认为最安全的方法是:
字符串
我不明白为什么库不直接用这种方式实现fclose。