Странная ошибка: [ArgumentOutOfRangeException: 'count' должен быть неотрицательным
У меня есть сайт, который работает в ASP.NET 3.5, NHibernate 2.2 и Sprint .NET для внедрения зависимостей. На нашем тестовом сервере возникает довольно странная ошибка, а также почти каждый раз, когда несколько пользователей онлайн. После возникновения проблемы эта ошибка отображается для каждого пользователя и каждого запроса, который они делают - до тех пор, пока вы не выполните IISRESET. Тогда все снова хорошо.
Вот исключение:
'count' must be non-negative.
Parameter name: count
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentOutOfRangeException: 'count' must be non-negative.
Parameter name: count
Source Error:
[No relevant source lines]
Source File: c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\4bf9aa39\6dcf5fc6\App_Web_z9ifuy6t.6.cs Line: 0
Stack Trace:
[ArgumentOutOfRangeException: 'count' must be non-negative.
Parameter name: count]
System.String.CtorCharCount(Char c, Int32 count) +10082288
Spring.Objects.Factory.Support.AbstractObjectFactory.GetObjectInternal(String name, Type requiredType, Object[] arguments, Boolean suppressConfigure) +3612
Spring.Objects.Factory.Support.AbstractObjectFactory.GetObject(String name) +75
Spring.Objects.Factory.Support.DefaultListableObjectFactory.GetObjectsOfType(Type type, Boolean includePrototypes, Boolean includeFactoryObjects) +365
Spring.Context.Support.AbstractApplicationContext.GetObjectsOfType(Type type, Boolean includePrototypes, Boolean includeFactoryObjects) +136
Spring.Context.Support.AbstractApplicationContext.GetObjectsOfType(Type type) +66
[ActivationException: Activation error occured while trying to get instance of type InfoTextService, key ""]
Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:57
Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance() in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:90
OurProjectsNamespace.Infrastructure.ObjectLocator.LocateService() +86
3 ответа
Это действительно очень странная ошибка. Когда вы смотрите на источник AbstractObjectFactory.GetObjectInternal
вы увидите следующую структуру:
[ThreadStatic]
private int nestingCount;
protected object GetObjectInternal(...)
{
const int INDENT = 3;
bool hasErrors = false;
try
{
nestingCount++;
if (log.IsDebugEnabled)
{
log.Debug("msg" +
new String(' ', nestingCount * INDENT));
}
// More code: Calls self recursively.
}
catch
{
nestingCount--;
hasErrors = true;
if (log.IsErrorEnabled)
{
log.Error("msg" +
new String(' ', nestingCount * INDENT));
}
}
finally
{
if (!hasErrors)
{
nestingCount--;
if (log.IsDebugEnabled)
{
log.Debug("msg" +
new String(' ', nestingCount * INDENT));
}
}
}
}
Исключение, которое вы видите, должно быть выброшено одним из трех new String(' ', nestingCount * INDENT)
звонки. Что конкретно string
вызов конструктора создает, когда предоставленное значение является отрицательным. Так как INDENT
это const, nestingCount
должен иметь отрицательное значение в этом случае. nestingCount
является потоковой статической переменной. Статические переменные потока всегда инициализируются со значением по умолчанию (в данном случае 0) и не могут зависеть от других потоков. Дальше больше, nestingCount
никогда не используется вне этого метода.
Так как nestingCount
является потоково-статическим и используется только в этом методе, трудно представить сценарий nestingCount
может стать отрицательным. Возможно, в случае асинхронного (ThreadAbort) исключения, но даже это мне сложно представить. Другой вариант заключается в том, что переменная-статическая переменная изменяется кем-то другим с помощью отражения.
Но большой вопрос: как это решить?
Решение:
Я могу думать только об одном: переконфигурировать log4net таким образом, чтобы отладочная информация не регистрировалась. При запрете отладочной информации string(char, int)
Конструктор, вероятно, никогда не будет вызван снова, что скроет проблему. Не очень красиво, но, возможно, эффективно. Это может сработать, потому что AbstractObjectFactory
журналы с использованием log
переменная, которая инициализируется следующим образом:
this.log = LogManager.GetLogger(this.GetType());
Вы можете сделать это, глобально отключив запись отладочной информации в log4net, или - когда вы думаете, что это излишне - настроив log4net для отключения отладочной информации для типа Spring.Objects.Factory.Support.DefaultListableObjectFactory
(экземпляр, который на самом деле вызывает исключение).
Удачи.
Я видел эту ошибку, когда столбец базы данных сопоставлен с более чем одним свойством. Типичный случай, когда столбец внешнего ключа сопоставляется со свойством и коллекцией. Вторая или третья пара глаз на файлы конфигурации помогает определить их.
Одним из недостатков этого является то, что это происходит для всех пользователей. У вас есть постоянный объект, который хранится в состоянии приложения?
В моем случае эта ошибка произошла через некоторое время во время тестирования производительности. Все начинается нормально, и через некоторое время появляется эта ошибка.
Оказывается, это было вызвано совершенно не связанной переменной [ThreadLocal], которую я использовал в своем коде. Я заменил его параметром метода, и теперь он работает нормально.