高速缓存键导致错误“对二进制补码数的最小值求反无效。”
这是我见过的最奇怪的错误之一。
我正在执行一个非常简单的调用以从 HttpRuntime 缓存返回值。调用是:
return HttpContext.Current.Cache[cacheKey];
如果返回 null,那就没问题。我检查返回的值是否为空并采取相应的行动。我已经使用这个电话很长时间了。
最近,由于某种原因,当cacheKey设置为这个精确值时:
"Topic_GridSelectAll:5,null,2010-08-31-20-00-00,Published,desc,5,1"
抛出System.OverflowException:否定二进制补码的最小值是无效的。
与调用、关联代码或服务器无关已经改变了。如果cacheKey 的字符略有不同,则它工作得很好。例如,此cacheKey返回null而不抛出任何异常:
"Topic_GridSelectAll:5,null,2010-08-31-21-00-00,Published,desc,5,1"
注意,这两个字符串之间的唯一区别是时间字符:2010-08-31-20-00-00与2010-08-31-21-00-00。
为什么这会有什么不同呢?为什么这么久之后还是现在呢?
堆栈跟踪是:
[OverflowException: Negating the minimum value of a twos complement number is invalid.]
System.Math.AbsHelper(Int32 value) +12753486
System.Web.Caching.CacheMultiple.UpdateCache(CacheKey cacheKey, CacheEntry newEntry, Boolean replace, CacheItemRemovedReason removedReason, Object& valueOld) +142
System.Web.Caching.CacheInternal.DoGet(Boolean isPublic, String key, CacheGetOptions getOptions) +122
MyProject.Helpers.CacheHelper.GetData(String cacheDomain, String cacheKey) in ...
我尝试更改缓存调用以使用 HttpRuntime.Cache(即 HttpRuntime.Cache[cacheKey]
),但这没有什么区别。我知道它是相同的底层缓存提供程序,但我认为不同的调用可能会产生影响。没有骰子。
This is one of the strangest errors I've ever seen.
I'm doing a very simple call to return values from the HttpRuntime cache. The call is:
return HttpContext.Current.Cache[cacheKey];
If it returns null, that's fine. I check if the returned value is null and act accordingly. I've been using this call for a long time.
Recently, for some reason, when cacheKey is set to this exact value:
"Topic_GridSelectAll:5,null,2010-08-31-20-00-00,Published,desc,5,1"
a System.OverflowException is thrown: Negating the minimum value of a twos complement number is invalid.
Nothing about the call, associated code or server has changed. If the cacheKey has slightly different characters, it works perfectly fine. For instance, this cacheKey returns null without throwing any exception:
"Topic_GridSelectAll:5,null,2010-08-31-21-00-00,Published,desc,5,1"
Notice, the only difference between those two strings is the time characters: 2010-08-31-20-00-00 versus 2010-08-31-21-00-00.
Why the hell would that make any difference? And why now after all this time?
The stack trace is:
[OverflowException: Negating the minimum value of a twos complement number is invalid.]
System.Math.AbsHelper(Int32 value) +12753486
System.Web.Caching.CacheMultiple.UpdateCache(CacheKey cacheKey, CacheEntry newEntry, Boolean replace, CacheItemRemovedReason removedReason, Object& valueOld) +142
System.Web.Caching.CacheInternal.DoGet(Boolean isPublic, String key, CacheGetOptions getOptions) +122
MyProject.Helpers.CacheHelper.GetData(String cacheDomain, String cacheKey) in ...
I've tried changing the cache call to use HttpRuntime.Cache instead (ie. HttpRuntime.Cache[cacheKey]
), but that made no difference. I know it's the same underlying cache provider, but I thought maybe the different call would make a difference. No dice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看起来在您的平台上,该确切字符串的
GetHashCode()
(在 System.String 中)正在返回-2147483648
。您可以通过将该字符串放入并简单地调用 GetHashCode() 来测试这一点(就像我所做的那样)。每个字符串都有一个哈希码,这就是一个。所以呢?好吧......CacheMultiple.UpdateCache
在您的密钥字符串上调用GetHashCode()
,然后调用GetCacheSingle()
,后者调用Math .Abs
,最终调用AbsHelper
。如果数字恰好等于-2147483648,AbsHelper 会抛出异常! (因为绝对值将比可容纳的最大值大 1)所以,恭喜您,您赢得了
GetHashCode
彩票 - 在 2^32 个可能的值中,您中奖了(好吧,错)一。不幸的是,似乎 Web.Cache 的内部根本不处理这个问题,因此您必须在字符串上调用GetHashCode
来查看它是否等于 -2147483648,如果是则更改弦稍。或者,捕获此异常 - 如果捕获,请在稍微更改密钥后重试(以可预测的方式,以便您可以再次以相同的方式重新创建它)。很好的错误发现 - 如果我是你,我可能会继续在 Connect 站点上放置错误...在我看来,由于内部实现,调用者不应该有责任检测和纠正边缘情况问题决定。
It looks like on your platform,
GetHashCode()
(in System.String) for that exact string is returning-2147483648
. You could test this (as I did) by putting that string in and simply calling GetHashCode() for it. Every string gets a hash code, and this is one. So what? well....CacheMultiple.UpdateCache
callsGetHashCode()
on your key string, then callsGetCacheSingle()
, which callsMath.Abs
, which eventually callsAbsHelper
. AbsHelper throws an exception if the number is exactly equal to -2147483648! (since the absoulte value would be one more than the maximum value that can be held)So, congratulations, you won the
GetHashCode
lottery - out of 2^32 possible values, you got the right (well, wrong) one. Unfortunately, it seems that the internals of Web.Cache don't handle this at all, so you would have to callGetHashCode
on your string to see if it was equal to -2147483648, and if so alter the string slightly. Or, trap for this exception - and if caught, try again after slightly altering your key (in a predictable manner so that you can recreate it the same way again).Nice bug find - I'd probably go ahead and put a bug on the Connect site if I were you... in my opinion, it shouldn't be the responsibility of the caller to detect and correct edge case problems due to internal implementation decisions.