奇怪的数组索引越界异常

Posted

技术标签:

【中文标题】奇怪的数组索引越界异常【英文标题】:Weird array index out of bounds exception 【发布时间】:2014-07-07 11:45:10 【问题描述】:

我的应用中有一些奇怪的东西我无法理解。

我正在实现一种算法,该算法检测何时产生脉冲响应(当强度值高于 0,2 时),当检测到它时,它会在脉冲刺激之前存储 0.5 秒的样本,并脉冲后的 1.5 秒。 在我检测到脉冲之前,所有样本都存储在 0.5 秒长的环形缓冲区中,当我产生脉冲时,下一个样本存储在 2 秒长的正常数组中,让一些空间稍后复制 0 ,5 秒的环形缓冲区样本。

问题是代码有时工作得很好,而其他时候它给了我数组索引超出范围的异常,如下所示:

07-07 13:31:47.312: E/androidRuntime(28823): java.lang.ArrayIndexOutOfBoundsException: length=16384; index=16384
07-07 13:31:47.312: E/AndroidRuntime(28823):    at com.example.acoustics.GrabaAudio.calculateImpulseLevel(GrabaAudio.java:174)

我真的不知道在我的代码中哪里可以产生这个超出数组范围的异常,所以这就是我不明白的。 缓冲区大小为 8192。

 private byte[] calculateImpulseLevel(byte[] array)
            byte[] circBuffer=new byte[bufferSize*2];
            for (int i=0; i<=array.length-3 ;i+=2)
            double sampleAmpl=(double)Math.abs((array[i+1] << 8 | array[i] & 0xff)/32767.0);
            if (sampleAmpl<0.2 && !triggered)
                int s=circ.size();
                if (s<circCapacity)
                    circ.add(array[i]);
                    circ.add(array[i+1]);
                 else 
                    circ.remove(0);
                    circ.add(array[i]);
                    circ.remove(0);
                    circ.add(array[i+1]);
                 
             else
                    if(!triggered)
                        triggered=true;
                    
                    indice = indice2+(bufferSize/2);//Empieza a poner en el array a partir de 0,5 seg de muestras
                    circBuffer[indice]=array[i];
                    circBuffer[indice+1]=array[i+1];
                    indice2+=2;
                    //if (indice >=((2*bufferSize)-3))
                    if (indice2 >=((3*bufferSize)/2)-3)
                        i=array.length-2;
                    

            
            

        System.arraycopy(toByteArray(circ),0,circBuffer,
              0,circ.size());
        //circ.removeAll(circ);
        return circBuffer;
    

由于这个错误只会发生几次,而且通常情况下,当我第一次编译我的应用程序设备时,它工作得很好,而且我运行我的应用程序越多,它就会变得越来越糟,我认为这可能是由存储在使用后未正确擦除的变量。

你们觉得呢?


好的,我对代码做了一些修改,已经解决了索引数组越界异常的问题。

这是我更改的代码:

if(!triggered)
                        triggered=true;
                    
                    indice=indice2+(bufferSize/2);
                    if (indice>2*bufferSize-2)
                        i=array.length;
                    else
                    circBuffer[indice]=array[i];
                    circBuffer[indice+1]=array[i+1];
                    indice2+=2;
                    
                    /*if (indice >=2*bufferSize-3)
                        i=array.length;
                    */

            

现在我遇到了一个新问题,当我在调试器模式下运行我的应用程序时,一切正常,但是,当我尝试在我的设备上正常运行它时,获得的音频数组显示为重复,它检测到脉冲响应总是在0,20 aprox 及其在 1,20 aprox 的重复版本,如下图所示:

(来源:subirimagenes.com)

这是我在调试器模式下得到的,实际上是我期望得到的:

(来源:subirimagenes.com)

为什么会这样?为什么只是在正常模式而不是在调试器中?

【问题讨论】:

GrabaAudio.java 的第 174 行是什么? circBuffer[indice]=array[i]; 我知道这一点。问题是我编码它的方式,显然这种情况不应该发生,但它确实发生了,我不知道我错过了什么。 length=16384; index=16384 索引应该是 16383。 indice2 只是一个初始化为 0 的局部变量。它将上升到 ((3*bufferSize)/2)-3 以确保我不会到达数组越界异常 【参考方案1】:
for (int i=0; i<=array.length-3 ;i+=2)

假设 array.lenght 是 100,那么最后一个索引是 99。那么条件就是 i&lt;=97

最后一次迭代的 i=96。并且将使用的数组的最高索引是:97,在边界内。

根据您提供的数据,变量的Indice max used index 为:

((3*bufferSize)/2)-3+(bufferSize/2) 等于2*bufferSize - 3

这比它的界限低 2 (bufferSize*2)。

一切似乎都井井有条。 Indice2 可能不是您让我们认为的那样。您可能想尝试将 bufferSize 设置为多 1 个字节,即byte[] circBuffer=new byte[bufferSize*2+1];

因为 16384 就是 8192*2。

【讨论】:

以上是关于奇怪的数组索引越界异常的主要内容,如果未能解决你的问题,请参考以下文章

数组操作的两个常见小问题越界和空指针

在android中,数据下标越界,则发生啥异常

ArrayList 中的索引越界异常

索引越界异常尝试使用 Swing 和 JOGL 创建窗口

Java IntelliJ 分析空指针异常、索引越界等代码的最佳方法是啥[关闭]

数组下标越界异常解决方法