C#,Index超出了数组的范围

时间:2011-11-29 02:47:17

标签: c# .net

此行引发异常:

int[] list = new int[count]; //Count = 52

功能是:

private static readonly Random _rand = new Random();
public static int[] GetList(int count)
    {
        int[] list = new int[count]; // this is line 21
        for (int i = 0; i < count; i++)
        {
            list[i] = i;
        }
        for (int i = 0; i < count * count; i++)
        {
            int i1 = _rand.Next(count);
            int i2 = _rand.Next(count);

            if (i1 == i2) continue;

            //swap values
            list[i1] ^= list[i2];
            list[i2] ^= list[i1];
            list[i1] ^= list[i2];
        }
        return list;
    }

编辑:

  

它可以正常使用2个月。但今天收到这个例外。

     

该程序是多线程程序。但只有一个线程使用此类。

     

这是发布模式,没有Visual Studio。

部分日志是:

  

索引超出了数组的范围。

     

位于C:\ Rm716b \ texasgame \ TexasHoldem \ trunk \ iCulture.GameFramework \ Util \ RandomList.cs:第21行的iCulture.GameFramework.Util.RandomList.GetList(Int32计数)

     

位于C:\ Rm716b \ texasgame \ TexasHoldem \ trunk \ iCulture.Texas \ Cards.cs:第18行的iCulture.Texas.Cards..ctor()

     

在iCulture.Texas.TexasGame..ctor(Player [] ParticipatePlayers,Int32 SmallBindAmount,Int32 SmallBlindPosition)C:\ Rm716b \ texasgame \ TexasHoldem \ trunk \ iCulture.Texas \ TexasGame.cs:第46行

编辑:

  

我试过反编译DLL,但代码逻辑保持不变。

可能是硬件错误导致此问题?因为从那时起它就不再出现了。

4 个答案:

答案 0 :(得分:2)

该方法工作正常。我跑了10000次,没有错误。

我唯一能想到的就是你在多线程应用程序中使用它。 Random类不是线程安全的,因此使用相同实例的线程可能会弄乱其内部值。在这种情况下,每个线程都应该有自己的随机生成器实例,你应该将其作为参数发送给方法。

您洗牌的方法效率不高。您应该使用Fisher.Yates算法,这是一个O(n)操作而不是O(n * n)。此外,您的方法对原始订单略有偏差,而这没有偏见:

public static int[] GetList(int count) {
  int[] list = new int[count];
  for (int i = 0; i < count; i++) {
    list[i] = i;
    // swap the item with any previous item, or itself
    int swap = _rand.Next(i + 1);
    if (swap != i) {
      int temp = list[i];
      list[i] = list[swap];
      list[swap] = temp;
    }
  }
  return list;
}

答案 1 :(得分:0)

我刚刚运行了您的代码,没有收到任何例外或错误。

这会将其缩小到您的_rand声明。你在指定种子价值吗?如果是这样,如果索引大于count,则可能会丢失索引。

你应该声明_rand类字段是这样的:

static Random _rand = new Random();

但是你列出的代码是工作代码。

逐步执行代码,查看_rand.Next(count)返回的内容。我保证你的阵列不是可用的索引。

答案 2 :(得分:0)

首先,不能在尚未声明的数组上抛出IndexOutOfBoundsException。

错误发生在没有附加调试器的发布模式下。这很好知道。请记住,当您的代码在发行版中编译并且未附加到调试器时,Visual Studio会进行重大优化。这引出了我的主要观点。

你被堆积的痕迹弄错了

我自己通过故意尝试访问数组外部的元素来证实这一点。堆栈跟踪表示错误发生在第36行,对我来说是return list;我引起的实际错误是在第31行插入的。

我怀疑堆栈跟踪并不是说该异常发生了什么功能。但我会说抛出异常的代码可能不是您在Visual Studio中看到的代码。

  1. 在发布模式下运行调试程序时是否会出现问题?

  2. 在反编译器中打开代码,例如this one。如果您浏览了上面的方法,源代码是否匹配(或多或少,反编译器并不完美)。

  3. 编辑:

    所以代码似乎是一样的。无论哪种方式,您获得的错误都不会发生在堆栈跟踪告诉您的行。在这一点上我无能为力,因为我无法访问违规的二进制文件。

    我的建议:当应用程序崩溃时,使用任务管理器保存程序内存的转储。 (或者,您可以使用AdPlusProcDump,以便在崩溃时自动执行此操作)。使用WinDbg打开转储并查看内存,堆栈跟踪,甚至是jitted方法,以尝试确定实际发生的位置。

    除此之外,在StackOverflow上你可以从其他任何人那里得到的东西并不多。像这样的虫子很痛苦,不幸的是每隔一段时间就会发生。

答案 3 :(得分:-1)

list[i1] ^= list[i2]; list[i2] ^= list[i1]; list[i1] ^= list[i2]; 这些代码行指向可能超出声明限制的值。 代码看起来很糟糕......你想要实现什么目标?