我一直在做一个Windows GUI应用程序,这意味着默认情况下它没有得到标准的输入/输出/错误句柄。这个GUI应用程序也是另一个GUI应用程序的子进程(渲染到一个嵌入式窗口中,标准句柄用于统一日志记录)。我们在现有代码中有一个断言,该断言将被子进程重用,其条件是_fileno(stderr) == 2。当根本没有标准句柄时,这个断言当然会失败,就像微软文档所说的那样返回-2。在进入这段代码之前,我调用了AllocConsole()函数来生成这些标准句柄。然而,对于AllocConsole(),断言仍然失败,因为_fileno(stderr)返回4。而且_fileno(stdout)看起来返回3.
我的理解是文件描述符是按创建的顺序编号的,从0开始。至少这是相同函数的POSIX文档,而不是WIN32。至少看起来WIN32函数是不兼容POSIX的。这本身并不令人惊讶。但我也没有在微软文档中看到任何解释这种行为偏差的内容。因此,如果最初没有标准句柄,为什么生成它们时不给它们预期的编号,0 (stdin) 1 (stdout) 2 (stderr)?如果新文件的编号开始于标准文件之后,我们是否应该期望_fileno(stderr) == 5而不是4,因为_fileno(stdin)将是3而不是_fileno(stdout) == 3?
仅供参考,我不是在这里找工作。我已经将wWinMain与wmain交换,并将子进程的项目更改为控制台应用程序。这样,一切都按预期进行。我只是在寻找一个解释为什么文件编号看起来如此错误。
所以如果最初没有标准句柄,为什么要生成它们呢没有给他们预期的编号,0 (stdin) 1 (stdout) 2 (stderr)?
根据AllocConsole
:
AllocConsole
初始化标准输入、标准输出和新控制台的标准错误句柄。标准输入句柄是控制台输入缓冲区的句柄,以及标准输出和标准错误句柄是控制台屏幕缓冲区的句柄。来检索这些句柄,使用GetStdHandle
函数。
说明AllocConsole
后有标准句柄。_fileno
返回-2的原因只是">stdout或stderr与输出流">不关联。
如果新文件的编号开始于标准文件之后,难道我们不应该期望_fileno(stderr) == 5而不是4吗_fileno(stdin)将是3而不是_fileno(stdout) == 3?
freopen
将生成一个新的fd,即从3开始,_fileno(stderr)
= 4的原因可能是您没有重新打开stdin
。
if (AllocConsole()) {
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
我将得到预期的3,4,5。
建议直接使用GetStdHandle
中返回的句柄,而不是文件描述符。