【问题标题】:How can I debug an "Index was out of range" exception? Or can I make VS enter debug mode when an exception is thrown?如何调试“索引超出范围”异常?或者我可以在抛出异常时让 VS 进入调试模式吗?
【发布时间】:2016-04-10 16:44:13
【问题描述】:

我的问题是我收到了一个 Index was out of range 异常,我想弄清楚这是在哪里发生的,以及导致错误的特定数组和索引是什么。我可以简单地通过我的程序来找到它,因为它使用访问运算符[] 的次数是数百万。那么有什么方法可以让我的程序“后退”并在抛出异常时进入调试模式?我不知道还有什么办法可以解决这个问题,除非通过可能需要几个小时的暴力破解。

这是一个完整的代码转储,以防万一:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace StringSet
{


    class StringSet
    {

        private List<List<string>> _Buckets;
        public int NumStrings { get; private set; }

        public StringSet ( ) 
        {
            this._Buckets = new List<List<string>>();
            this.NumStrings = 0;
        }

        public StringSet ( string[] S )
        {
            // better way to do this?
            this._Buckets = new List<List<string>>();
            foreach ( string s in S ) this._Buckets.Add(new List<string>());
            foreach ( string s in S ) { this.Insert(s);  }
        }

        private int _GetBucketNumber ( string s, List<List<string>> Buckets )
        {
            //       s: string whose index to look up
            // Buckets: source buckets

            // disallow empty or NULL strings
            if ( String.IsNullOrEmpty(s) ) { throw new ArgumentException("Cannot add empty or NULL string to set"); }
            if ( Buckets.Count == 0 ) { throw new ArgumentException("Tried to call _GetBucketNumber on empty bucket list"); }

            // Bernstein hash
            // http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx           
            int result = (int)s[0];
            for ( int i = 1; i < s.Length; ++i ) { result = 33 * result + (int)s[i]; }
            return result % Buckets.Count;
        }

        private void _RehashIfNecessary ( )
        {
            // if the number of strings in the set exceeds the number of buckets, 
            // increase the number of buckets to either double its current size 
            // or the largest number of buckets possible, whichever is smaller
            if ( this.NumStrings > this._Buckets.Count )
            {
                List<List<string>> NewBuckets = new List<List<string>>(Math.Min(this._Buckets.Count * 2, Int32.MaxValue));
                foreach ( List<string> Bucket in this._Buckets )
                {
                    foreach ( string s in Bucket )
                    {
                        NewBuckets[this._GetBucketNumber(s, NewBuckets)].Add(s);
                    }
                }
                this._Buckets = NewBuckets;
            }
        }

        public void Insert ( string s )
        {
            // disallow empty or NULL strings
            if ( String.IsNullOrEmpty(s) ) { throw new ArgumentException("Cannot add empty or NULL string to set"); }

            // Get bucket that string belongs in
            int k = this._GetBucketNumber(s, this._Buckets);
            if (k >= this._Buckets.Count) { Console.WriteLine("Found problem! GetBucketNumber return {0}, whichs is bigger or equal to than this._Buckets.Count={1}", k, this._Buckets.Count); }
            List<string> Bucket = this._Buckets[this._GetBucketNumber(s,this._Buckets)];
            // Add if not already there
            if ( Bucket.IndexOf(s) == -1 ) { Bucket.Add(s); }
            ++NumStrings; _RehashIfNecessary();
        }

        public bool Contains ( string s )
        {
            // returns true or false depending on whether s is a 
            // string currently in the set
            return (this._Buckets[this._GetBucketNumber(s,this._Buckets)].IndexOf(s) != -1);
        }

        public void RunPerformanceTest ( )
        {
            // tests string hash set against regular List<string> 
            // in terms of lookup

            // create list of all elements in hash set
            List<string> ListVersion = new List<string>(),
                                Copy = new List<string>();
            foreach ( List<string> Bucket in this._Buckets )
            {
                foreach ( string Str in Bucket )
                {
                    ListVersion.Add(Str);
                    Copy.Add(Str);
                }                    
            }

            // calculate average time to look up all elements
            Stopwatch Watch = new Stopwatch();
            long tList = 0, tHset = 0; // ms
            foreach ( string Str in Copy )
            {
                // measure time to look up string in ordinary list
                Watch.Start();
                if ( ListVersion.Contains(Str) ) { }
                Watch.Stop();
                tList += Watch.ElapsedTicks;
                // now measure time to look up same string in my hash set
                Watch.Reset();
                Watch.Start();
                if ( this.Contains(Str) ) { }
                Watch.Stop();
                tHset += Watch.ElapsedTicks;
                Watch.Reset();
            }
            int n = Copy.Count;
            Console.WriteLine("Average ticks to look up in List: {0}", tList / n);
            Console.WriteLine("Average ticks to look up in hashset: {0}", tHset / n);
        }

        public void Print ( )
        {
            for ( int i = 0; i < this._Buckets.Count; ++i )
            {
                Console.WriteLine("Bucket {0}: {1}", i, string.Join(",",this._Buckets[i].ToArray()));
            }
        }

    }

    class Program
    {
        static void Main ( string[] args )
        {

            try
            {
                List<string> Words = new List<string>();
                Console.WriteLine("Reading dictionary words from text file into hash set ...");
                System.IO.StreamReader file = new System.IO.StreamReader(System.AppDomain.CurrentDomain.BaseDirectory + "testfiles\\dictionary.txt");
                string line; 
                while ( (line = file.ReadLine()) != null )
                {
                    Words.Add(line);
                }
                Console.WriteLine("DONE!");
                StringSet TestSet = new StringSet(Words.ToArray());
                Console.WriteLine("Running performance test ...");
                TestSet.RunPerformanceTest();
                Console.WriteLine("DONE!");
            }
            catch ( Exception E )
            {
                Console.WriteLine("Exception occured: {0}", E.Message);
            }
            Console.Read(); // just to keep console open
        }
    }
}

【问题讨论】:

  • 检查异常发生时的堆栈跟踪。问题是您已经捕获了Exception,然后只是简单地转储了消息,注释掉 try/catch 块,Visual Studio 应该在抛出异常时停止。
  • 您的 try/catch 不足,只会妨碍您的程序调试。 Do it correctly.

标签: c# .net visual-studio


【解决方案1】:

是的,您可以在抛出错误时让 VS 停止。它可能在版本之间略有不同,但通常在菜单上:Debug > Exceptions...

然后展开 Common Language Runtime Exceptions - System 并在 Thrown 列中为您的异常打勾

【讨论】:

    猜你喜欢
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多