为什么我得到这个堆栈溢出异常

本文关键字:堆栈 栈溢出 异常 为什么 | 更新日期: 2023-09-27 18:12:30

我正在编写《俄罗斯方块》的克隆,这是我真正做过的最大的项目。在实现行删除代码时,我已经开始收到堆栈溢出异常。我认为这可能与我庞大的集合或Linq的低效率使用有关。下面是导致问题的具体方法:

void MoveAllAboveDown(int row)
    {
        List<Block> newBlockList = new List<Block>();
        for (int rowCheck = row; rowCheck > _VertOffset; --rowCheck)
        {
            for (int i = _HorizOffset; i < _HorizOffset + _Width; ++i)
            {
                //If the spot above this is filled
                if (_blockList.Where(block => block.Contains(new Vector2(i, rowCheck - 1))).ToList().Count > 0)
                {
                    //insert block here
                    newBlockList.Add(new Block(new Vector2(i, rowCheck), new[,] { { true } }, Color.Black, _texture));
                }
                else
                {
                    var list = _blockList.Where(tempBlock => tempBlock.Contains(new Vector2(i, rowCheck - 1))).ToList();
                    if (list.Count > 0)
                        list.ElementAt(0).Delete(new Vector2(i, rowCheck - 1));
                }
            }
        }
        for (int rowToDelete = row; rowToDelete > _VertOffset; --rowToDelete)
        {
            DeleteRow(rowToDelete);
        }
        foreach (Block block in newBlockList)
        {
            _blockList.Add(block);
        }
    }

如果我能弄清楚如何(甚至使用一个单独的网站,如果我必须),我将附加整个源。

如果你喜欢的话,我真的不介意有人来看看整个代码库,告诉我我写错了什么(比如命名约定、算法等)。显然,这不是这个网站的目的,但我想我应该把它扔进去,因为我无论如何都要攻击代码库。

编辑:下面是主要的游戏文件:http://pastebin.com/PqVAS56U
下面是剩下的代码:http://pastebin.com/JjBKZgwN

Edit2:我相信这是一个堆栈跟踪:

'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_32'mscorlib'v4.0_4.0.0.0__b77a5c561934e089'mscorlib.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Users'Patrick'Desktop'OldComp'Users'patrick'Documents'Visual Studio 2010'Projects'Tetris'Tetris'Tetris'bin'x86'Debug'Tetris.exe', Symbols loaded.
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_32'Microsoft.Xna.Framework.Game'v4.0_4.0.0.0__842cf8be1de50553'Microsoft.Xna.Framework.Game.dll'
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_32'Microsoft.Xna.Framework.Graphics'v4.0_4.0.0.0__842cf8be1de50553'Microsoft.Xna.Framework.Graphics.dll'
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_32'Microsoft.Xna.Framework'v4.0_4.0.0.0__842cf8be1de50553'Microsoft.Xna.Framework.dll'
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_MSIL'Microsoft.Xna.Framework.Input.Touch'v4.0_4.0.0.0__842cf8be1de50553'Microsoft.Xna.Framework.Input.Touch.dll'
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_MSIL'System.Drawing'v4.0_4.0.0.0__b03f5f7f11d50a3a'System.Drawing.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_MSIL'System'v4.0_4.0.0.0__b77a5c561934e089'System.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_MSIL'System.Windows.Forms'v4.0_4.0.0.0__b77a5c561934e089'System.Windows.Forms.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_MSIL'Microsoft.Xna.Framework.GamerServices'v4.0_4.0.0.0__842cf8be1de50553'Microsoft.Xna.Framework.GamerServices.dll'
'Tetris.exe' (Managed (v4.0.30319)): Loaded 'C:'Windows'Microsoft.Net'assembly'GAC_MSIL'System.Core'v4.0_4.0.0.0__b77a5c561934e089'System.Core.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Process is terminated due to StackOverflowException.
The program '[7484] Tetris.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

为什么我得到这个堆栈溢出异常

如果不跟踪其余的代码,我怀疑部分原因是在:

中使用了row而不是rowToDelete
for (int rowToDelete = row; rowToDelete > _VertOffset; --rowToDelete)
{
    // DeleteRow(row); // Woops! Typo
    DeleteRow(rowToDelete);
}

编辑:如果不在那里,那么很可能在DeleteRow中。

我没有看到您减少传递给MoveAllAboveDown()然后传递给DeleteRow()row的值。您的DeleteRow()函数再次使用相同的row号码调用MoveAllAboveDown()

所以它们会一直互相调用直到StackOverflow。

我认为你得到一个堆栈跟踪的原因是MoveAllAboveDown(int row)调用DeleteRow(int row)调用MoveAllAboveDown(int row)创建一个无限循环,正如已经由cornerback84指出的。

这里有一些其他的技巧:

    您在问题中编辑的不是堆栈跟踪,而是跟踪输出
    • 堆栈跟踪表示打印出调用堆栈,它将显示嵌套的当前执行的方法。
    • 在Visual Studio菜单中选择Debug> Windows> call stack查看调用堆栈。要复制调用堆栈以粘贴到问题中,请在异常助手对话框中单击"复制异常详细信息"。
  • 既然你问了关于命名约定等的评论,我建议你看看:
    • Microsoft命名指南
    • StyleCop(这是优秀的!)
    • 作为额外提示,检查FxCop也-你会学到很多,保证:)