JAVA BufferOverflowException,同时保持缓冲区容量?

时间:2016-06-25 21:51:19

标签: java buffer-overflow bytebuffer

所以我有一个从ByteBuffer创建IntBuffer的方法:

public static IntBuffer directIntBuffer(int[]buffer){
        ByteBuffer bb = ByteBuffer.allocateDirect(4*buffer.length);
        bb.order(ByteOrder.nativeOrder());
        IntBuffer ib = bb.asIntBuffer();
        ib.put(buffer).flip();
        return ib;
    }

在另一个类的构造函数中,我初始化其中一个IntBuffers并用嵌套的for循环填充它:

编辑:所以这是我的完整构造函数。我用实际顶点坐标填充FloatBuffer FBVertices,并用索引填充IntBuffer IBVerticesIndex。稍后,我使用GL11.glDrawElements(GL11.GL_TRIANGLES,IBVerticesIndex)绘制这些;

public sphereHelper(float fRadius, int iSlices, int iStacks)

{  
    FBVertices = GLDrawHelper.directFloatBuffer(new float[iSlices*iStacks*4*3]); 
    FBVertices.clear();

    IBVerticesIndex = GLDrawHelper.directIntBuffer(new int[iSlices*iStacks*4]);
    IBVerticesIndex.clear();
    int index=0;




    float verticalDegreePerStack= (float)Math.PI/iStacks; //1*Pi because we only want the height of the sphere once (from -PI/2 to PI/2)
    float horizontalDegreePerSlice = 2.0f* (float)Math.PI/iSlices; //2*Pi because of unit circle/polar coordinates going once around the sphere

    for (int k=0; k< iStacks; k++)
    {
        //overall vertical angle
        float rho= (float)k*verticalDegreePerStack;
        //sinus of that angle
        float srho =(float) (Math.sin(rho));

        float crho = (float) (Math.cos(rho));

        //sinus and cosinus of vertical angle+ angle of 1 stack
        float srhodrho= (float) (Math.sin(rho + verticalDegreePerStack));
        float crhodrho = (float) (Math.cos(rho + verticalDegreePerStack));

        for (int j=0; j<iSlices;j++)
        {
            //overall angle along the horizontal border (0 degree at full 2*PI circle)
            float theta = (j==iSlices)? 0.0f : j*horizontalDegreePerSlice;
            //sinus and cosinus
            float stheta = (float)(-Math.sin(theta));
            float ctheta = (float)(Math.cos(theta));

            //coordinates of first vertex of current triangle
            float x=stheta*srho;
            float z=ctheta*srho;
            float y=crho;


            //put coordinates of first vertex into buffer
            FBVertices.put(new float[]{x*fRadius,y*fRadius,z*fRadius});

            //put index of first vertex of polygon in index array, increase index counter by one
            if (IBVerticesIndex.position()<IBVerticesIndex.capacity())
            {IBVerticesIndex.put(index);}
            index++;
            //second vertex
            x = stheta*srhodrho;
            z = ctheta*srhodrho;
            y = crhodrho;

            //put these coordinates into Buffer
            FBVertices.put(new float[] {x*fRadius,y*fRadius,z*fRadius});


             if (IBVerticesIndex.position()+2<IBVerticesIndex.capacity())
            {
            IBVerticesIndex.put(new int[] {index,index+1,index+2});}
            index++;

            System.out.println(IBVerticesIndex.position()+"/"+IBVerticesIndex.capacity());

        }
        IBVerticesIndex.flip();
        FBVertices.flip();

       }
    }

我在此输出中得到一个BufferOverflowException:

  

4/400 8/400 12/400 16/400 20/400 24/400 28/400 32/400 36/400 40/400

     

线程中的异常&#34; main&#34; java.nio.BufferOverflowException

所以它在缓冲区容量的第10位溢出? 我在开头清除()缓冲区,因此应该重置位置。

感谢您的投入!

1 个答案:

答案 0 :(得分:0)

编辑: +1给Arjan对原始问题的评论。我将Don的代码复制到我的机器上,它正在使用Java 8,也可以将400/400作为输出。您是否在已注明的代码中的其他位置设置了limit

您是否了解了Buffer superclass的工作原理?具体来说,该类具有limit属性,该属性没有记录良好的初始值。写过limit值会引发BufferOverflowException

在我看来,您希望将此IntBuffer用作原始数组,在这种情况下,在初始化例程中,您需要在调用后将limit设置为capacityflip(),根据文档将limit重置为mark