c++ - ofstream的close方法是否也关闭底层句柄

标签 c++ windows iostream

在Windows平台上,调用CreateFile得到一个文件句柄,然后用这个句柄初始化一个ofstream对象。一个最小的例子如下:

#include"stdafx.h"
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <windows.h>
#include <io.h>
#include <fcntl.h>

class CSV_writer {
public:
    std::ofstream my_ofstream;
private:
    HANDLE my_handle = INVALID_HANDLE_VALUE;
    int file_descriptor = -1;
    FILE * my_file = nullptr;   //FILE type is actually a IO buff.
    const static unsigned int fl = 256;
public:
    explicit CSV_writer(const TCHAR * file_name_) {
    //get current directory
    TCHAR current_path[MAX_PATH];
    GetCurrentDirectory(MAX_PATH, current_path);

    TCHAR filename[fl]{ 0 };
    _tcscat_s(filename, file_name_);
    _tcscat_s(filename, _T(".csv"));
    if (current_path[_tcslen(current_path) - 1] != _T('\\') && _tcslen(current_path) < MAX_PATH - 1) {
        _tcscat_s(current_path, _T("\\"));
    }
    else {
        throw std::exception("path length exceeding limit.");
    }

    if (_tcslen(current_path) + _tcslen(filename) + 1 < MAX_PATH) {
        _tcscat_s(current_path, filename);
    }
    else {
        //current path exceeds the max path length defined in MAX_PATH
        throw std::exception("path length exceeding limit.");
    }

    this->my_handle = CreateFile(
        current_path,
        GENERIC_READ | GENERIC_WRITE,   //access permit, both read and write
        0,          //cannot be shared and cannot be opened again until the handle to the file or device is closed
        nullptr,    //returned handle can not be inherited by child process
        CREATE_ALWAYS,  //always create a new file, overwrite old one if it exists
        FILE_ATTRIBUTE_NORMAL,
        nullptr
    );

    if (my_handle != INVALID_HANDLE_VALUE) {
        int file_descriptor = _open_osfhandle((intptr_t)my_handle, _O_TEXT);
        if (file_descriptor != -1) {
            this->my_file = _fdopen(file_descriptor, "w");
            if (this->my_file != nullptr) {
                this->my_ofstream = std::ofstream(this->my_file);

            }
        }
    }
}

~CSV_writer() {
    // Closes stream, file, file_descriptor, and file_handle.
    this->my_ofstream.flush();
    this->my_ofstream.close();
    this->my_file = nullptr;
    this->file_descriptor = -1;
    this->my_handle = INVALID_HANDLE_VALUE;
}
};

int main(int argc, char* argv[])
{
    CSV_writer csv_writer(L"memory_layout");
    csv_writer.my_ofstream << "Type,\t" << "Size,\t" << "Offset,\t" <<   "Address\n";

    return 0;
}

我的问题是,之后调用“my_ofstream.close()”后,底层文件句柄是否也会释放?或者我必须在调用 close() 之后手动调用 Windows API CloseHandle()?

更新:对于那些说没有使用 FILE* 的 ofstream 构造函数的人,实际上有,有点,see the screen shot below

最佳答案

我希望您已经知道您正在使用的构造函数:

std::ofstream(FILE * fp)

是一个非标准的、未记录的 Microsoft 扩展,甚至 Microsoft 也不保证。

在那种情况下,Microsoft 甚至不会向您 promise :

int fd = ...;
...
FILE * fp = _fdopen(fd, "w");
...
std::osftream ofs(fp);
...
ofs.close();

将执行 fclose(fp) - 没关系 _close(fd)

但是,如果您认为 ofs.close() fclose(fp) - 显然您会这样做 - 那么 Microsoft 确实向您保证它也会 _close(fd)。来自 the documentation

Remarks

...

File descriptors passed into _fdopen are owned by the returned FILE * stream. If _fdopen is successful, do not call _close on the file descriptor. Calling fclose on the returned FILE * also closes the file descriptor.

(我的重点。)

关于c++ - ofstream的close方法是否也关闭底层句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52751344/

相关文章:

windows - 通过批处理文件使用 findstr 删除特定子文件夹

windows - 从 VBScript 中的 cmd/c 命令获取返回值

c++ - 如何在 C++ 中对文件系统进行非并发打印?

c++ - 线程安全的 cout 技术。我错过了什么吗?

c++ - Openmp thread affinity : Set 2 threads in the program, 有多少核正在运行?

c++ - 如何使用 C++ 在列表框中显示字符串?

c++ - OpenCL 全局/本地工作大小选择

c++ - 使用 cout 输出 cerr

c++ - g++ 4.4.7 -std=gnu++0x 应该编译 "for each"构造吗?

作为接口(interface)的 C++20 概念