fgets返回空

时间:2012-11-06 17:43:48

标签: c visual-studio-2010 process pipe fgets

从父进程,我试图通过标准输入/输出控制子进程。 我使用以下MSDN示例来创建子进程并重定向其标准输入&输出:http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.100%29.aspx

在父方面,我使用以下代码发送相同的“命令”两次:

const char cmd[] = "test\n";
DWORD written, read;
BOOL success;
success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);
success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);

在孩子方面,我通过 fgets 调用阅读这些命令。 第一个命令按预期读取。但是当发送第二个命令时,fgets调用返回一个空字符串,并且下一个fgets调用不会返回。这是子进程代码:

char *retStrP;
char str[256];
size_t strLen;

retStrP = fgets(str, 256, stdin);
strLen = strlen(str);
if (retStrP != str)
{
    char errorStr[256];
    int a = feof(stdin);
    int b = ferror(stdin);
    sprintf(errorStr, "Fgets error, %d %d\n", a, b);
    OutputDebugString(errorStr);
}
else if (strLen == 0)
{
    char errorStr[256];
    int a = feof(stdin);
    int b = ferror(stdin);
    sprintf(errorStr, "Strlen is 0, %d %d\n", a, b);
    OutputDebugString(errorStr);
}

从前面的代码中,第二次调用fgets的行为如下:返回的指针等于str缓冲区,但strlen为0。

当阅读MSDN fgets文档(http://msdn.microsoft.com/en-us/library/c37dh6kf%28v=vs.100%29.aspx)时,我没有看到任何方式它可以将指针返回到作为第一个参数传递的缓冲区,并将第一个缓冲区的字节设置为0(到目前为止)缓冲区大小大于1)。 如果发生错误或达到文件结尾,则fgets应返回NULL,feof或ferror应返回不为0的内容。

我怀疑管道处理出了什么问题,但我无法弄清楚是什么......从父方面来看,我对stdin写入管道没有做什么比发送两次相同的缓冲区更多。 知道什么可能导致这种行为?

2 个答案:

答案 0 :(得分:0)

你的问题与你所链接的例子非常模糊。这里有一些建议。

试试这个:

while(!success)
   success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);
while(!success)
   success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);

原因: 如果WriteFile()函数成功,则返回值为非零(TRUE)。 如果函数失败或异步完成,则返回值为零(FALSE)。要获取错误信息,请使用GetLastError()函数。

使用ReadFile()代替fgets在子进程的for循环中读取WriteFile()写入的数据。

如果您仍然遇到问题,请在代码中的GetLastError()WriteFile()之后使用ReadFile()功能,并发布您的错误代码信息。我们或许可以帮助你。

答案 1 :(得分:0)

我发现了问题!

从父进程,WriteFile调用将NULL终止字符发送到管道。

因此,在第一次WriteFile调用之后,fgets将字符串读取到换行符。 然后在第二个WriteFile调用中,fgets读取从前一个NULL终止字符开始直到第二个换行符的字符串。它导致返回的字符串,第一个字符是NULL终止字符。 这就是fgets返回没有错误但字符串长度为0的原因。

然后解决方案是不通过从cmd缓冲区大小中减去1来发送NULL终止字符。