缓存键导致错误"否定二进制补码的最小值无效".

soh*_*970 19 c# asp.net integer httpruntime.cache

这是我见过的最奇怪的错误之一.

我正在做一个非常简单的调用来从HttpRuntime缓存中返回值.电话是:

return HttpContext.Current.Cache[cacheKey];
Run Code Online (Sandbox Code Playgroud)

如果它返回null,那很好.我检查返回的值是否为null并相应地采取行动.我一直在使用这个电话.

最近,出于某种原因,当cacheKey设置为这个确切的值时:

"Topic_GridSelectAll:5,null,2010-08-31-20-00-00,Published,desc,5,1"
Run Code Online (Sandbox Code Playgroud)

抛出System.OverflowException:否定二进制补码数的最小值无效.

呼叫,相关代码或服务器没有任何变化.如果cacheKey的字符略有不同,那么它的工作原理非常好.例如,此cacheKey返回null而不抛出任何异常:

"Topic_GridSelectAll:5,null,2010-08-31-21-00-00,Published,desc,5,1"
Run Code Online (Sandbox Code Playgroud)

请注意,这两个字符串之间的唯一区别是时间字符: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 ...
Run Code Online (Sandbox Code Playgroud)

我已经尝试更改缓存调用以使用HttpRuntime.Cache(即.HttpRuntime.Cache[cacheKey]),但这没有任何区别.我知道它是相同的底层缓存提供者,但我想也许不同的调用会产生影响.没有骰子.

Phi*_*eck 18

它看起来像在您的平台上GetHashCode()(在System.String中),因为该字符串正在返回-2147483648.您可以通过将该字符串放入其中并简单地为其调用GetHashCode()来测试此(就像我一样).每个字符串都有一个哈希码,这是一个.所以呢?好....

CacheMultiple.UpdateCache调用GetHashCode()你的密钥字符串,然后调用GetCacheSingle(),Math.Abs最后调用的调用AbsHelper.如果数字正好等于-2147483648,AbsHelper会抛出异常!(因为absoulte值比可以保持的最大值多一个)

所以,恭喜你,你赢了GetHashCode彩票 - 在2 ^ 32个可能的值中,你得到了正确的(好的,错误的).不幸的是,似乎Web.Cache的内部根本不处理这个,所以你必须调用GetHashCode你的字符串来查看它是否等于-2147483648,如果是这样,稍微改变字符串.或者,捕获此异常 - 如果被捕获,请稍微更改您的密钥后再次尝试(以可预测的方式,以便您可以再次以相同的方式重新创建它).

好的bug发现 - 如果我是你的话,我可能会继续在Connect网站上添加一个bug ...在我看来,由于内部实现,查询和纠正边缘案例问题不应该是调用者的责任决定.