0

我有一个函数,我在其中调用了 _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;
}
4

2 回答 2

1

很简单:如果你可以打开它但不再需要它,请关闭它。所以:

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;
}
于 2015-12-03T19:51:46.903 回答
1

如果你成功创建了一个管道popen但不调用pclose,那么FILE对象占用的内存不会被释放。更糟糕的是,还有外部可见的后果。由可能创建的子进程popen可能会徘徊。当您popen使用fork. 相应的waitpid可能不会发生,直到pclose被调用。(我相信这是一个典型的、显而易见的实现,也是我为其他编程语言实现类似 popen 的函数的方式。)

尽管 Win32 没有forkand wait,但在 Microsoft C 库的_popen. 管道句柄可能有一个进程的FILE内部 Win32 句柄,它不受调用CloseHandleuntil的影响。_pclose加上其他资源,如与该进程通信的 Win32 管道。如果你不关闭管道,那么你就会泄漏这些资源。

关于传递空指针。这是原始 POSIX 函数的禁忌。pclose如果在空指针上调用,则未定义行为。POSIX 说“[i]如果 pclose() 的参数流不是指向由 popen() 创建的流的指针,则 pclose() 的结果是未定义的。” (空指针不是指向流的指针,即使它是由 返回的popen)。

Microsoft 允许_pclose使用空指针调用。这在 MSDN 中有记录,其行为是_pclose返回 -1 并将errno伪变量设置为EINVAL.

如果您想要移植基于这些函数的代码,则需要考虑这一点。

于 2015-12-03T20:09:32.963 回答