Ключ кеширования вызывает ошибку «Недопустимое отрицание минимального значения числа дополнения до двух». - PullRequest
19 голосов
/ 01 сентября 2010

Это одна из самых странных ошибок, которые я когда-либо видел.

Я делаю очень простой вызов для возврата значений из кэша HttpRuntime. Вызов:

return HttpContext.Current.Cache[cacheKey];

Если он возвращает ноль, это нормально. Я проверяю, является ли возвращаемое значение нулевым, и действую соответственно. Я давно пользуюсь этим звонком.

В последнее время по какой-то причине, когда cacheKey установлен на это точное значение:

"Topic_GridSelectAll:5,null,2010-08-31-20-00-00,Published,desc,5,1"

Выдается исключение System.OverflowException: Недопустимое отрицание минимального значения числа дополнения до двух.

Ничего в вызове, связанном коде или сервере не изменилось. Если cacheKey имеет немного другие символы, он работает отлично. Например, этот cacheKey возвращает ноль без каких-либо исключений:

"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]), но это не имело значения. Я знаю, что это один и тот же поставщик кеша, но я подумал, что, возможно, другой вызов будет иметь значение. Без кубиков.

1 Ответ

17 голосов
/ 01 сентября 2010

Похоже, на вашей платформе GetHashCode() (в System.String) для этой точной строки возвращает -2147483648.Вы можете проверить это (как я сделал), вставив эту строку и просто вызвав для нее GetHashCode ().Каждая строка получает хеш-код, и это один.И что?ну ....

CacheMultiple.UpdateCache вызывает GetHashCode() на вашей ключевой строке, затем вызывает GetCacheSingle(), что вызывает Math.Abs, что в итоге вызывает AbsHelper.AbsHelper выдает исключение, если число точно равно -2147483648!(поскольку абсолютное значение будет на единицу больше максимального значения, которое может быть удержано)

Итак, поздравляю, вы выиграли лотерею GetHashCode - из 2 ^ 32 возможных значений вы получили право (хорошо, неправильный.К сожалению, кажется, что внутреннее содержимое Web.Cache вообще не обрабатывает это, поэтому вам нужно будет вызвать GetHashCode в вашей строке, чтобы увидеть, было ли оно равно -2147483648, и, если это так, слегка изменить строку.Или перехватите это исключение - и, если его поймали, попробуйте еще раз после небольшого изменения ключа (предсказуемым образом, чтобы вы могли воссоздать его таким же образом).

Отличный поиск ошибки - я, вероятно, пойдуопередив и разместив ошибку на сайте Connect, если бы я был вами ... по моему мнению, вызывающая сторона не должна отвечать за обнаружение и исправление краевых проблем из-за внутренних решений реализации.

...