GetFreeDiskSpaceEx 如何返回(看似)错误的磁盘空间量?
因此,我使用可以输出大图像(从 30MB 到 2GB 以上)的设备。在开始创建这些映像之一之前,我们通过 GetDiskFreeSpaceEx 检查是否有足够的磁盘空间。通常(在本例中)我们会写入同一网络上的共享文件夹。正在运行的磁盘空间没有用户配额。
昨晚,为了准备演示,我们开始了测试运行。在跑步过程中,我们经历了一次失败。我们需要 327391776
字节,但被告知我们只有 186580992
可用。来自 GetDiskFreeSpaceEx
的数字是:
用户可用空间:186580992
可用总可用空间:186580992
这些对应于两个(输出)参数 lpFreeBytesAvailable
和 lpTotalNumberOfFreeBytes
中的 QuadPart
变量获取DiskFreeSpaceAvailable
。
该代码已使用多年,我从未见过漏报。下面是完整的函数:
long IsDiskSpaceAvailable( const char* inDirectory,
const _int64& inRequestedSize,
_int64& outUserFree,
_int64& outTotalFree,
_int64& outCalcRequest )
{
ULARGE_INTEGER fba;
ULARGE_INTEGER tnb;
ULARGE_INTEGER tnfba;
ULARGE_INTEGER reqsize;
string dir;
size_t len;
dir = inDirectory;
len = strlen( inDirectory );
outUserFree = 0;
outTotalFree = 0;
outCalcRequest = 0;
if( inDirectory[len-1] != '\\' )
dir += "\\";
// this is the value of inRequestSize that was passed in
// inRequestedSize = 3273917760;
if( GetDiskFreeSpaceEx( dir.c_str(), &fba, &tnb, &tnfba ) )
{
outUserFree = fba.QuadPart;
outTotalFree = tnfba.QuadPart;
// this is computed dynamically given a specific compression
// type, but for simplicity I had hard-coded the value that was used
float compressionRatio = 10.0;
reqsize.QuadPart = (ULONGLONG) (inRequestedSize / compressionRatio);
outCalcRequest = reqsize.QuadPart;
// this is what was triggered to cause the failure,
// i.e., user free space was < the request size
if( fba.QuadPart < reqsize.QuadPart )
return( RetCode_OutOfSpace );
}
else
{
return( RetCode_Failure );
}
return( RetCode_OK );
}
因此,值 3273917760
被传递给函数,它是压缩前所需的磁盘空间总量。该函数将其除以10
的压缩比以获得所需的实际大小。
当我检查共享所在的磁盘时,它有大约 177GB 的可用空间,远远超过报告的数量。再次开始测试后,没有更改任何内容,它就起作用了。
所以我的问题是;什么会导致这样的事情?据我所知,这不是一个编程错误,并且正如我之前提到的,这段代码已经使用了很长一段时间,没有任何问题。
我检查了远程计算机的事件日志,在故障发生时没有发现任何有趣的事情。我希望有人以前见过类似的东西,提前致谢。
So I work on a device that outputs large images (anywhere from 30MB to 2GB+). Before we begin creating one of these images we check to see if there is sufficient disk space via GetDiskFreeSpaceEx
. Typically (and in this case) we are writing to a shared folder on the same network. There are no user quotas on disk space at play.
Last night, in preparation for a demo, we kicked off a test run. During the run we experienced a failure. We needed 327391776
bytes and were told that we only had 186580992
available. The numbers from GetDiskFreeSpaceEx
were:
User free space available: 186580992
Total free space available: 186580992
Those correspond to the QuadPart
variables in the two (output) arguments lpFreeBytesAvailable
and lpTotalNumberOfFreeBytes
to GetDiskFreeSpaceAvailable
.
This code has been in use for years now and I have never seen a false negative. Here is the complete function:
long IsDiskSpaceAvailable( const char* inDirectory,
const _int64& inRequestedSize,
_int64& outUserFree,
_int64& outTotalFree,
_int64& outCalcRequest )
{
ULARGE_INTEGER fba;
ULARGE_INTEGER tnb;
ULARGE_INTEGER tnfba;
ULARGE_INTEGER reqsize;
string dir;
size_t len;
dir = inDirectory;
len = strlen( inDirectory );
outUserFree = 0;
outTotalFree = 0;
outCalcRequest = 0;
if( inDirectory[len-1] != '\\' )
dir += "\\";
// this is the value of inRequestSize that was passed in
// inRequestedSize = 3273917760;
if( GetDiskFreeSpaceEx( dir.c_str(), &fba, &tnb, &tnfba ) )
{
outUserFree = fba.QuadPart;
outTotalFree = tnfba.QuadPart;
// this is computed dynamically given a specific compression
// type, but for simplicity I had hard-coded the value that was used
float compressionRatio = 10.0;
reqsize.QuadPart = (ULONGLONG) (inRequestedSize / compressionRatio);
outCalcRequest = reqsize.QuadPart;
// this is what was triggered to cause the failure,
// i.e., user free space was < the request size
if( fba.QuadPart < reqsize.QuadPart )
return( RetCode_OutOfSpace );
}
else
{
return( RetCode_Failure );
}
return( RetCode_OK );
}
So, a value of 3273917760
was passed to the function which is the total amount of disk space needed before compression. The function divides this by the compression ratio of 10
to get the actual size needed.
When I checked the disk that the share resides on it had ~177GB free, far more than what was reported. After starting the test again without changing anything it worked.
So my question here is; what could cause something like this? As far as I can tell it is not a programming error and, as I mentioned earlier, this code has been in use for a very long time now with no problems.
I checked the event log of the remote machine and found nothing of interest around the time of the failure. I'm hoping that someone out there has seen something similar before, thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可能没有任何用处,但“奇怪”的是:
177GB ~= 186580992 * 1000。
这可以通过代码中其他地方发生的堆栈损坏(因为您没有初始化局部变量)来解释。
代码“inRequestedSize/compressionRatio”不必使用浮点数进行除法,并且由于您已经通过强制转换消除了“转换松散精度”警告,因此您实际上也可能会遇到错误(但是在示例应该有效)。您可以简单地执行“inRequestedSize / 10”。
最后但并非最不重要的一点是,您没有说明代码在哪里运行。在移动设备上,GetDiskFreeSpaceEx 的文档指出:
Might not be of any use, but it's "strange" that:
177GB ~= 186580992 * 1000.
This could be explained by a stack corruption (since you don't initialize your local variable) happening elsewhere in the code.
The code "inRequestedSize / compressionRatio" doesn't have to be using float for the division, and since you've silented the "conversion loose precision" warning with the cast, you might actually hit an error too (but the number given in the example should work). You could simply do "inRequestedSize / 10".
Last but not least, you don't say where the code is running. On Mobile, the documentation of GetDiskFreeSpaceEx states: