Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Under what circumstance System.Collections.ArrayList.Add throws IndexOutOfRangeException?

We are experiencing weird bug at production environment we cannot debug nor inject logging code. I am trying to figure this up but following stack trace confuse me.

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.ArrayList.Add(Object value)
   at ...

According to the MSDN Add method should only throw NotSupportedException.

I have no idea what's going on here. Do you?

like image 734
Jakub Šturc Avatar asked Sep 25 '10 14:09

Jakub Šturc


People also ask

What is System IndexOutOfRangeException?

An IndexOutOfRangeException exception is thrown when an invalid index is used to access a member of an array or a collection, or to read or write from a particular location in a buffer. This exception inherits from the Exception class but adds no unique members.

Which Exception type is thrown in an attempt to Index an array via an Index that is less than zero or outside the bounds of the array?

The ArrayIndexOutOfBoundsException is one of the most common errors in Java. It occurs when a program attempts to access an invalid index in an array i.e. an index that is less than 0, or equal to or greater than the length of the array.

How to catch Index Out of bounds Exception in c#?

Use Try-Catch: Consider enclosing your code inside a try-catch statement and manipulate the exception accordingly. As mentioned, C# won't let you access an invalid index and will definitely throw an IndexOutOfRangeException.


2 Answers

It boils down to List not being thread safe. I have had IndexOutOfRangeException occuring when iterating over a list after adding items using multiple threads without synchronization. The code below could corrupt the items count and result in IndexOutOfRangeException while iterating the list subsequently,

List<TradeFillInfo> updatedFills = new List<TradeFillInfo>();
Parallel.ForEach (trades, (trade) =>
{
    TradeFillInfo fill = new TradeFillInfo();

    //do something

    updatedFills.Add(fill); //NOTE:Adding items without synchronization
});

foreach (var fill in updatedFills) //IndexOutOfRangeException here sometimes
{
    //do something
}

Synchronizing the Add() with a lock statement will fix the issue.

lock (updatedFills)
{
    updatedFills.Add(fill);
}
like image 148
Nemo Avatar answered Sep 27 '22 18:09

Nemo


The IndexOutOfRangeException is thrown when "an attempt is made to access an element of an array with an index that is outside the bounds of the array."

Note that the ArrayList class is not thread-safe. It is possible that in multi-threaded scenarios, race-conditions will result in the ArrayList attempting to read/write to the backing array at indices that are outside its range.

Example: One thread reduces the size of the backing array (perhaps through a TrimToSize call) at the same time that another thread is adding to the collection. Now, if the backing array is at full capacity, the adding thread will attempt to expand its capacity (by allocating a new array) to accomodate the new element. The simultaneous TrimToSize call then reverses this effect. Then, by the time the adding thread attempts to write to the array, the index that it thought was available would no longer be, causing the exception to be thrown.

Fix: Use thread-safe constructs, as appropriate to your situation.

like image 29
Ani Avatar answered Sep 27 '22 19:09

Ani