翻译《The Old New Thing》- How to check for errors from SetFilePointer

Choosing a provocative debug signature - The Old New Thing (microsoft.com)icon-default.png?t=N7T8https://devblogs.microsoft.com/oldnewthing/20070604-00/?p=26583

Raymond Chen 2007年07月11日


  SetFilePointer函数以两种不同的方式报告错误,这取决于你是否传递了NULL作为lpDistanceToMoveHigh参数。MSDN中的文档是正确的,但我发现人们更喜欢我以不同的方式重述相同的事实,所以这里是文档的表格版本。

If lpDistanceToMoveHigh == NULLIf lpDistanceToMoveHigh != NULL
If successretVal != INVALID_SET_FILE_POINTERretVal != INVALID_SET_FILE_POINTER ||
GetLastError() == ERROR_SUCCESS
If failedretVal == INVALID_SET_FILE_POINTERretVal == INVALID_SET_FILE_POINTER &&
GetLastError() != ERROR_SUCCESS

 

        我想展示一些示例代码,但MSDN中的文档已经包含了lpDistancetoMoveHigh == NULL情况和lpDistancetoMoveHigh != NULL情况的示例代码。

        一个常见的错误是在返回值不是INVALID_SET_FILE_POINTER的情况下调用GetLastError。换句话说,人们忽略了“函数成功还是失败?”测试中的retVal == INVALID_SET_FILE_POINTER部分。仅仅因为GetLastError()返回了一个错误代码,并不意味着SetFilePointer函数失败了。返回值也必须是INVALID_SET_FILE_POINTER。我必须承认MSDN中的文档在这一点上可以更清晰,但示例代码希望解决任何悬而未决的歧义。

        但为什么当lpDistanceToMoveHigh不是NULL时,SetFilePointer使用这种奇怪的错误报告方式呢?MSDN文档也解释了这个细节:如果文件大小大于4GB,那么INVALID_SET_FILE_POINTER是文件位置低阶32位的有效值。例如,如果你将指针移动到位置0x00000001FFFFFFFF,那么*lpDistanceToMoveHigh将被设置为结果的高阶32位(1),返回值是结果的低阶32位(0xFFFFFFFF,恰好是INVALID_SET_FILE_POINTER的数值)。在那种情况下(只有在那种情况下),系统需要使用SetLastError(ERROR_SUCCESS)来告诉你,“不,那个值是完全正常的。它只是巧合等于INVALID_SET_FILE_POINTER`”。

        为什么不在所有成功路径上调用SetLastError(ERROR_SUCCESS),而不仅仅是当结果的低阶32位恰好是0xFFFFFFFF的时候呢?这只是Win32的一个通用约定:如果函数成功,它不需要调用SetLastError(ERROR_SUCCESS)。成功的返回值告诉你函数成功了。这个约定的例外是当返回值是模糊的,就像我们在这里有当结果的低阶32位恰好是0xFFFFFFFF。

        你可能会认为这是一个愚蠢的约定。但木已成舟,在时间旅行技术落地之前,你只能接受现实。(请注意,UNIX使用相同的约定与errno变量。只有在之前的函数调用失败时,errno的值才被定义。)

        回顾过去,SetFilePointer的设计者有点过于聪明了。他们试图将32位和64位文件管理合并到一个单一的函数中。“它是通用的!”问题在于,你必须以两种不同的方式检查错误,这取决于你是使用32位变体还是64位变体。幸运的是,内核团队意识到他们的聪明反被聪明误,并想出了一个新函数SetFilePointerEx。该函数直接产生一个64位值,返回值是一个简单的BOOL,这使得检查成功或失败变得简单。

        练习:GetFileSize函数是怎么回事?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0x0007

可不可奖励我吃只毛嘴鸡 馋😋

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值