我有一个函数,在其中我多次调用_open。
如果_popen
返回NULL
,我是否需要在函数返回之前调用_pclose
?
我已经标记了3个我认为可能需要调用_pclose
的位置。
我必须在以下哪个位置拨打_pclose
?
bool theFunction()
{
FILE* pPipe;
char buffer[1000];
if( (pPipe = _popen("dir", "rt")) == NULL )
{
//location 1
_pclose(pPipe);
return false;
}
while(fgets(pipeBuffer, maxBufferSize, pPipe))
{
printf(pipeBuffer);
}
if( (pPipe = _popen("cls", "rt")) == NULL )
{
//location 2
_pclose(pPipe);
return false;
}
//location 3
_pclose(pPipe);
return true;
}
简单:如果可以打开但不再需要,请关闭管道。因此:
bool theFunction()
{
FILE* pPipe;
char buffer[1000];
if( (pPipe = _popen("dir", "rt")) == NULL )
{
return false;
}
while(fgets(pipeBuffer, maxBufferSize, pPipe))
{
printf(pipeBuffer);
}
// The fact that you have to close it here in the middle of nowhere
// should ring a bell that you need to think about separation of concern
_pclose(pPipe);
if( (pPipe = _popen("cls", "rt")) == NULL )
{
return false;
}
_pclose(pPipe);
return true;
}
如果使用popen
成功创建管道,但未调用pclose
,则不会释放FILE
对象占用的内存。更糟糕的是,还有外部可见的后果。由popen
创建的子进程可能会徘徊。当您使用popen
时,会使用fork
创建一个流程。相应的CCD_ 12可能直到调用CCD_。(我相信这是一个典型的、显而易见的实现,这也是我为其他编程语言实现类似popen的函数的方式。)
尽管Win32没有fork
和wait
,但在Microsoft C库的_popen
中可能存在类似的资源问题。FILE
管道句柄可能有一个进程的内部Win32句柄,在调用_pclose
之前,该进程不受CloseHandle
的约束。加上其他资源,如与该进程通信的Win32管道。如果你不关闭管道,那么你就会泄漏这些资源。
关于传递空指针。这是对原始POSIX函数的否定。如果在空指针上调用pclose
,则不会定义该行为。POSIX表示"[i]如果pclose()的参数流不是popen()创建的流的指针,则pclose的结果是未定义的。"(空指针不是指向流的指针(即使它是由popen
返回的)。
Microsoft允许使用空指针调用_pclose
。MSDN中对此进行了说明,其行为是_pclose
返回-1并将errno
伪变量设置为EINVAL
。
如果您想要移植基于这些函数的代码,则需要考虑这一点。