Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array boundaries on java and .length

Tags:

java

android

keys array have been defined as follows:

    keys = new char[] {resolv, 'А', 'Б', 'В', 'Г', 'Д', 'Е', 
                                'Ё', 'Ж', 'З', 'И', 'Й', 'К', 
                                'Л', 'М', 'Н', 'О', 'П', 'Р', 
                                'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 
                                'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь',
                                'Э', 'Ю', 'Я'};

'resolv' is a constant char value of 0x00, but that's not relevant for this issue.

Now, this code raises "java.lang.ArrayIndexOutOfBoundsException: length=34; index=34" exception sometimes:

protected void LoadKeyRects() {
    keyRects = new Rect[keys.length];
    // Solve key
    keyRects[0] = resRect;


    // Rest of keys
    int x, y;
    for (int i=1; i<keys.length; i++) {
        y = 214 + ( 87 * ((i-1)/11));
        x = 7 + (((i-1)%11)*71);
        keyRects[i] = new Rect (x, y, x+71, y+87);
    }
}

So far I haven't been able to reproduce the error by myself, but I have got enough reports from BugSense in third party devices to be concerned about it. It seems like sometimes keyRects[i] may refer to keyRects[keys.length] despite the i

Any ideas?

like image 769
Fran Marzoa Avatar asked Oct 02 '22 12:10

Fran Marzoa


1 Answers

I can see the problem in the for loop. You use out-of-scope field to end your iteration, which is simply wrong, if you're not accessing the field itself. Also if you did, you should do it differently. Two examples:

protected void LoadKeyRects() {
    keyRects = new Rect[keys.length];
    // Solve key
    keyRects[0] = resRect;


    // Rest of keys
    int x, y;
    for (int i=1; i<keyRects.length; i++) {
        y = 214 + ( 87 * ((i-1)/11));
        x = 7 + (((i-1)%11)*71);
        keyRects[i] = new Rect (x, y, x+71, y+87);
    }
}

This will work properly without any ArrayIndexOutOfBoundsException for sure. If you need to access or even modify the keys array, do it that way:

protected void LoadKeyRects() {
    final char[] localKeys = keys;

    keyRects = new Rect[localKeys.length];
    // Solve key
    keyRects[0] = resRect;


    // Rest of keys
    int x, y;
    for (int i=1; i<localKeys.length; i++) {
        y = 214 + ( 87 * ((i-1)/11));
        x = 7 + (((i-1)%11)*71);
        keyRects[i] = new Rect (x, y, x+71, y+87);
    }

    // if you need to change the keys, uncomment the next line
    // keys = localKeys;
}
like image 165
Tadeas Kriz Avatar answered Oct 07 '22 19:10

Tadeas Kriz