【问题标题】:Controlling inheritability of file handles created by C++ std::fstream in Windows控制 C++ std::fstream 在 Windows 中创建的文件句柄的可继承性
【发布时间】:2019-04-04 10:46:33
【问题描述】:

在 Windows 中,使用CreateProcess 创建进程时,可以将true 作为bInheritHandles 参数传递。

CreateProcess( , , , , bInheritHandles, , , , )

这意味着所有标记为可继承的文件句柄实际上都将被子进程继承。

如何控制C++std::fstream类创建的底层文件句柄是否可继承?

【问题讨论】:

  • 你不能。如果您打算继承,请使用 CreateFile()。
  • 但是,至少如果使用 MSVC,有一种方法可以首先从 HANDLE 获取 FILE*,然后将 std::fstream 绑定到该 FILE*。
  • 何必为这一切而烦恼。由于必须使用 API,因此只能使用 API,不要同时使用 API 和 std。
  • @MichaelChourdakis, fstream 对象更容易使用。通过使用运算符<<>>,您可以自动解析和字符串化变量。
  • @Mercalli 与 API 相比,所有 std 对象的功能都受到限制,并且仅对基本处理级别有用。在全高度项目中,您需要更多功能,这意味着 API。此外,您仍然可以使用缓冲区级别的流函数,然后使用 API 将缓冲区写入文件。

标签: c++ winapi fstream child-process filehandle


【解决方案1】:

C 运行时默认创建可继承句柄。

ofstream outFile("filename.txt") ;
CreateProcess("program.exe", ..., true, ...) ; //program.exe will inherit the above file handle

所以,如果你想继承一个句柄,你不需要做任何事情。

如果您不想继承句柄,则必须使用 WinAPI 函数 SetHandleInformation 自己设置句柄的 HANDLE_FLAG_INHERIT 标志,如下所示:

FILE* filePtr = fopen("filename.txt", "w") ;
SetHandleInformation( (HANDLE)_get_osfhandle(_fileno(filePtr)), HANDLE_FLAG_INHERIT, 0) ;
ofstream outFile(filePtr) ;

在上面的第三行中,构造函数ofstream(FILE*) 是对Visual Studio 中存在的标准的扩展(我不知道其他编译器)。

在构造函数之后,filePtr 现在归outFile 所有,因此调用outFile.close() 也会关闭filePtr。您可以完全忘记 filePtr 变量。

文档:fopen_fileno_get_osfhandleSetHandleInformation

【讨论】:

【解决方案2】:

如果您使用fopen 打开文件,您可以在fopen 参数中指定Windows 特定的"N" 模式以使句柄不可继承。

例子:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  FILE *fp = fopen("SomeFile.txt", "rwN");
  if (!fp) {
    return -1;
  }

  system("SomeProcess.exe");

  fclose(fp);
  return 0;
}

来源:

https://wiki.sei.cmu.edu/confluence/display/c/WIN03-C.+Understand+HANDLE+inheritance

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=vs-2019

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2012-04-04
    • 2010-12-20
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 2010-10-31
    相关资源
    最近更新 更多