当提升内存映射文件分配的磁盘空间超过HDD上的可用空间时,如何检测错误
How can detect error when boost memory mapped file allocated more disk space than is free on HDD
在我的建模代码中,我使用boost内存映射文件来分配磁盘上的大型ish数组。
它工作得很好,但我找不到一种方法来检测我分配的数组大于磁盘drivw上可用空间的情况。例如,以下代码将愉快地执行(假设我在HDD上的可用空间小于8E9字节):
boost::iostreams::mapped_file_params file_params;
file_params.path = path;
file_params.mode = std::ios::in | std::ios::out;
file_params.new_file_size = static_cast<size_t>(8E9); # About 10GB
file_params.length = static_cast<size_t>(8E9);
boost::iostreams::mapped_file result;
result.open(file_params);
我甚至可以在resuld.data()
上工作,直到我写入未分配的部分内存(因为HDD上缺少空间),然后我得到以下错误:
memory access violation at address: 0x7e9e2cd1e000: non-existent physical address
在我得到神秘的memory access violation
之前,有什么方法可以检测到这个错误吗?
我实际上测试了这一点:如果文件大于分区上的可浏览可用空间,则代码会违反内存访问规则,如果文件较小,则代码可以工作(我通过更改分区上的可用空间而不是编辑代码来测试它)。
可能的解决方案
如果我的std:fill
文件内容为零,我仍然会得到memory access violation
,但这个错误位于分配附近,更容易调试。我宁愿想办法提出一个例外。
您可以使用fallocate
或posix_fallocate
为文件预先预留空间。这样你就知道你永远不会"过度投入"。当然,在最初创建时,它有一个性能缺陷。
出于安全原因,操作系统可能会将fallocate
上的块清零。
fallocate
允许您进行未写入的扩展,但它在第一次访问时仍然为零。在windows上,可以使用SetFileValidData
来解决这一问题。
请注意,带有O_DIRECT
+fallocate()
的Linux仍然使用相当大的CPU(与Windows的SetFileValidData
相反),尽管IO带宽通常是瓶颈,但如果同时进行大量CPU工作,这仍然会对性能产生显著影响。
在我遇到神秘的内存访问违规之前,有什么方法可以检测到这个错误吗?
当您只更改文件的大小时,它将是sparse
,这意味着没有数据的区域不会占用磁盘空间。空间是在写入过程中分配的,可能会造成磁盘空间不足的错误。
解决这个问题的一种方法是将(伪)数据写入文件,而不仅仅是更改大小。这需要更多的时间,但您只会在第一个写入周期内耗尽磁盘空间,因为文件在写入后会有最终大小。
- 使用命名空间时出现多个定义错误
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 从类型列表中递归删除重复项会导致编译器堆空间错误 (VS2017)
- 我该怎么做才能摆脱使用命名空间时的语法错误?
- C++ Visual Studio 错误:名称后跟'::'必须是类或命名空间名称 (DirectX 11)
- 名称后跟"::"必须是类或命名空间错误,即使"::"后面是类名
- fstream.h 中的 STL 命名空间错误与 qmake/make.
- 在 main() 中使用 getline() 函数时出现命名空间错误
- C++命名空间错误:不是命名空间的成员
- 为什么我得到这个不是类或命名空间错误的'enum'?
- C++内存分配/释放和自由空间错误
- C++命名空间错误
- C++ Visual Studio 2015 CLR Windows 窗体命名空间错误
- LNK 2019命名空间错误
- Gsoap:如何解决引用组时的命名空间错误
- 变量已定义,命名空间错误
- c++初学者:使用命名空间错误
- Swig命名空间错误?不是一个有效的基类
- 命名空间错误'Not a namespace-name'
- 名称空间错误