【问题标题】:Weird error: [ArgumentOutOfRangeException: 'count' must be non-negative奇怪的错误:[ArgumentOutOfRangeException:'count' 必须为非负数
【发布时间】:2010-11-22 15:00:06
【问题描述】:

我有一个在 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

【问题讨论】:

    标签: asp.net nhibernate orm dependency-injection spring.net


    【解决方案1】:

    这确实是一个非常奇怪的错误。当您查看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 是一个常量,所以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 类型的调试信息(实际导致异常的实例) .

    祝你好运。

    【讨论】:

    • 禁用调试 Spring.Objects.Factory.Support.DefaultListableObjectFactory 是一个可行的想法。我会试试这个,看看错误不会再次发生。这个错误肯定很奇怪,但很有趣。希望根本原因仅限于此错误...谢谢史蒂文!如果有任何新内容出现,我会保持更新。
    • @Mattias:我很好奇我的观察是否正确以及禁用调试是否确实解决了您的问题。
    • 希望我能尽快给您答复。这只发生在尚未上线的生产服务器上。所以下次更新后我们会看到。
    • 我会将您的答案标记为已接受,因为它非常有见地。到目前为止,顺便说一句。
    • 已经投产几个月了,一直看不到错误。再次感谢!
    【解决方案2】:

    我看到当数据库列映射到多个属性时会发生此错误。一个典型的情况是外键列映射到属性和集合。对配置文件的第二或第三双眼睛有助于发现这些。

    其中一个转折点是它发生在所有用户身上。您是否有存储在应用程序状态中的持久对象?

    【讨论】:

    • 由于机密性,我无法发布所有代码,但正在定位的对象是一个内部对象,具有 ISession 和 ExceptionHandler 作为构造函数参数。初始化该对象时出现错误。跨度>
    【解决方案3】:

    在我的例子中,这个错误是在性能测试的一段时间后发生的。它开始正常,一段时间后弹出此错误。

    原来它是由我在代码中使用的完全不相关的 [ThreadLocal] 变量引起的。我用方法参数替换了它,现在它可以正常工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多