c# - 内存不足和溢出异常创建小数组

标签 c# arrays xna out-of-memory overflowexception

我是 C# 和 XNA 的新手。刚刚设法编写了一个生成三角形网格的类。 但是有一个问题。我可以获得最多 27 个节点长度的三角形。 在 28 时抛出内存不足异常,在 31 时抛出 -overFlow 异常。

我不明白它是如何溢出或内存不足的...试图 计算所有这些内存值,但它们看起来非常小。

它只是受变量影响的节点数组。节点类不是很大:

float x; 4乙 float y; 4乙 float z; 4乙 int[] con;整数[6] 4*6=24 B 字节传递; 1乙 颜色列; 32b=4B

            Total:  41B

创建三角形所需节点的序列和为n(n+1)/2

28 岁时内存不足

28*29/2=406个节点

总内存:

41*406 = 16646 B = 16.26kB

31 处的溢出:496 个节点是 19.9 kB

我确实读过关于“内存不足异常”的文章,结构的大小比看起来的要大,内存不足发生在 500MB 的大小......我的小三角形不可能达到这么大的大小。

这是我的整个类(class):

class TriMatrix
    {
        int len;
        int Lenght;
        Node[] node;
        VertexPositionColor[] vertex;

        public class Node
        {
            public float x;
            public float y;
            public float z;
            public int[] con;
            public byte pass;
            public Color col;
            public Node(byte passable)
            {
                pass = passable;
                if (pass > 0)
                { col = Color.Green; }
                else
                { col = Color.DarkRed; }
                x = 0;
                z = 0;
                con = new int[6];
            }
        }

        public TriMatrix(int lenght)
        {
            len = lenght;
            Lenght = 0;
            byte pass;
            Random rnd = new Random();
            for (int i = 0; i <= len; i++)
            {
                Lenght += Lenght + 1;
            }
            node = new Node[Lenght];
            int num = 0;
            for (int i = 0; i < len; i++)
            {
                for (int j = 0; j <= i; j++)
                {

                    if (rnd.Next(0, 5) > 0) { pass = 1; } else { pass = 0; }
                    node[num] = new Node(pass);
                    node[num].x = (float)i - (float)j / 2.0f;
                    node[num].y = 0;
                    node[num].z = (float)j * 0.6f;
                    if (i < len - 1) { node[num].con[0] = num + i; } else { node[num].con[0] = -1; node[num].col = Color.Violet; }
                    if (i < len - 1) { node[num].con[1] = num + i + 1; } else { node[num].con[1] = -1; }
                    if (j < i) { node[num].con[2] = num + 1; } else { node[num].con[2] = -1; node[num].col = Color.Violet; }
                    if (j < i) { node[num].con[3] = num - i; } else { node[num].con[3] = -1; }
                    if (i > 0) { node[num].con[4] = num - i - 1; } else { node[num].con[4] = -1; }
                    if (i > 0) { node[num].con[5] = num - 1; } else { node[num].con[5] = -1; }
                    if (j == 0) { node[num].col = Color.Violet; }
                    num++;
                }
            }
        }

        public void Draw(Effect effect, GraphicsDevice graphics)
        {
            VertexPositionColor[] verts = new VertexPositionColor[3];
            int num = 0;
            for (int i = 0; i < len-1; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
                        verts[1] = new VertexPositionColor(new Vector3(node[num + i + 1].x, node[num + i + 1].y, node[num + i + 1].z), node[num + i + 1].col);
                        verts[2] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
                        graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);

                        if ( j < i)
                        {
                            verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
                            verts[1] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
                            verts[2] = new VertexPositionColor(new Vector3(node[num + 1].x, node[num + 1].y, node[num + 1].z), node[num + 1].col);
                            graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);
                        }
                    }
                    num++;
                }
            }
        }
    }// endclass

最佳答案

我假设你的错误在于这个循环(冒昧地纠正你的拼写):

for (int i = 0; i <= len; i++)
{
    Length += Length + 1;
}

在循环中,Length 的值本身 加一。这实际上意味着每次迭代都将 Length 的值加倍,从而导致指数增长。

在前几次迭代中,Length 的值将是:1、3、7、15、31、63,...。我们可以概括这个序列,使得在迭代 i 时,Length 的值将为 2i+1 -1。在第 28 次迭代中,这将是 536,870,911。在第 31 次迭代中,这将是 4,294,967,295。

编辑:正如您在下面的评论中提到的,计算长度为 len 的三角形网格中的元素数量的正确解决方法是:

for (int i = 1; i <= len; i++)
{
    Length += i;
} 

这等同于求和 1 + 2 + 3 + … + len,它计算出所谓的 triangular number .它可以使用以下公式简洁地计算:

Length = len * (len + 1) / 2;

这个数字之所以增长如此之大,是因为它是平方关系;对于长度为 n 的边,您需要的面积大约为 的一半。

关于c# - 内存不足和溢出异常创建小数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12866939/

相关文章:

xna - 如何解析边界顶点的图像?复杂物体几何(远见物理学)

c# - XNA 数字锁定影响输入

c# - 如何通过工作线程更新 ObservableCollection?

c# - Cookie.ExpireTimeSpan 被忽略并在 CookieAuthentication 中设置为 Session

c# - C#中DTO(数据传输对象)和代理对象的区别

c# - 如何将公钥存储在机器级 RSA key 容器中

PHP for 循环与带范围的 foreach

MySQL 合并来自多个 JSON 行的数组

方法中的 C# 默认值 - 编译错误 : compile-time constant

javascript - MD 数组 : Add additional array if value isn't found