此行引发异常:
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,但代码逻辑保持不变。
可能是硬件错误导致此问题?因为从那时起它就不再出现了。
答案 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中看到的代码。
在发布模式下运行调试程序时是否会出现问题?
在反编译器中打开代码,例如this one。如果您浏览了上面的方法,源代码是否匹配(或多或少,反编译器并不完美)。
编辑:
所以代码似乎是一样的。无论哪种方式,您获得的错误都不会发生在堆栈跟踪告诉您的行。在这一点上我无能为力,因为我无法访问违规的二进制文件。
我的建议:当应用程序崩溃时,使用任务管理器保存程序内存的转储。 (或者,您可以使用AdPlus或ProcDump,以便在崩溃时自动执行此操作)。使用WinDbg打开转储并查看内存,堆栈跟踪,甚至是jitted方法,以尝试确定实际发生的位置。
除此之外,在StackOverflow上你可以从其他任何人那里得到的东西并不多。像这样的虫子很痛苦,不幸的是每隔一段时间就会发生。
答案 3 :(得分:-1)
list[i1] ^= list[i2];
list[i2] ^= list[i1];
list[i1] ^= list[i2];
这些代码行指向可能超出声明限制的值。
代码看起来很糟糕......你想要实现什么目标?