在我的build模代码中,我使用boost 内存映射文件来分配磁盘上的大数组。
它运作良好,但我无法find一种方式来检测我分配磁盘驱动器上的空闲空间大于数组的情况。 例如下面的代码将会愉快地执行(假设我在硬盘上的可用空间less于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上缺less空间),然后出现以下错误:
memory access violation at address: 0x7e9e2cd1e000: non-existent physical address
有没有什么办法来检测这个错误之前,我得到神秘的memory access violation
?
我实际上testing了这一点:如果文件比分区上的avilable可用空间大,则代码具有内存访问冲突,如果代码更小(我通过更改分区上的空间而不是通过编辑代码来testing它)。
可能的解决scheme
如果我std:fill
用零std:fill
文件内容我仍然得到memory access violation
,但这个错误位于分配附近,更容易debugging。 我宁愿要某种方式来引发exception。
您可以使用fallocate
或posix_fallocate
来fallocate
为文件预留空间。 这样你就知道你永远不会“过度犯下”了。 它有一个性能上的缺点,当然在初始创建时。
出于安全原因,操作系统可能fallocate
上的块fallocate
。
fallocate
可以让你做不成文的范围,但它在第一次访问时仍然是零。 在Windows上,这可以使用, SetFileValidData
让你绕过即使。
请注意,使用O_DIRECT
+ fallocate()
Linux仍然使用相当多的CPU(而不是Windows的SetFileValidData
),尽管IO带宽通常是瓶颈,但是如果您同时在做大量的CPU工作,这仍然会带来明显的性能影响。
有没有什么办法来检测这个错误之前,我得到神秘的内存访问冲突?
当你只是改变一个文件的大小,它将是sparse
,这意味着没有数据的区域不占用磁盘空间。 空间在写入过程中分配 – 可以创建磁盘空间错误。
解决问题的一种方法是将(虚拟)数据写入文件,而不是仅仅改变大小。 这需要更多的时间,但是在第一个写入周期中,您只能获取磁盘空间,因为文件之后会有最终的大小。