EListError List index out of bounds (0) - TForm item

11,024

Solution 1

Three possible causes:

  • A memory overwrite which happens to overwrite things in "accessible" memory (so no AV). But triggers an invalid change to FormListObject.

  • Something else (something like OnShow event) is actually removing items from FormListObject. It doesn't have to be a different thread; but of course that's also possible. NOTE: Although you asked if it's a GUI threading issue, I really doubt this is the case because you would have to be specifically calling GUI code from a different thread for this possibility.

  • Re-entrant code is causing FormListObject to be changed while in the middle of the loop. This happens when you call Application.ProcessMessages while in the middle of processing another message. My debuggey-sense is twitching on this one. Even if you aren't guilty of the Application.ProcessMessages sin, some component on the form you're showing may be.

PS: I notice in a comment you say you already have a stack-trace. Check further down the stack-trace, and see if your code is re-entrant.


Since you're unable to reproduce the issue, you need extra debug logging to get more info. Assuming you have Log method that simply appends to a debug file. (The log method should output current thread ID to confirm threading issues.) Add debug logging as follows:

Log('Start loop');
for ii := FormListObject.Count - 1 downto 0 do begin
   // Error happens here
   TForm(FormListObject[ii]).Show;
end;
Log('End loop');

Encapsulate your FormListObject so that any code to remove/delete/clear items goes through code under your control. I.e. don't expose direct access to the underlying list which would allow rogue code to change the list without your kowledge. Then add logging on any method that can remove items:

Log(Format('(%p)FormListObject.Clear', [Pointer(Self)]));

It might also be useful to log creation/destruction of FormListObject instances.


When the issue occurrs, you'll have to analyse the log file to determine what went wrong. For example, if my hunch about the most likely cause of the issue is correct, you might find the following pattern (note each entry is on the same thread):

(Thread X) Start Loop
(Thread X) Start Loop
(Thread X) End Loop
(Thread X) ($........) Clear

EDIT

I've added a third possibility; which I actually have a hunch is the most likely cause.
Also added some specific debugging suggestions to narrow it down.

Solution 2

The error I get is on a TList object: "[EListError] List index out of bounds (0)".

This is simple to understand. You have an empty list and are attempting to access an element at index zero.

Use the debugger to tell you which list is empty. Get the debugger to break on exceptions. And then try to work out why your code assumes the the list is not empty when that is not so.

Share:
11,024
Alex
Author by

Alex

Updated on June 04, 2022

Comments

  • Alex
    Alex almost 2 years

    I have this interesting bug that I need to fix. I've couple of solutions ready but before I implement one of them I like to ask why such an error may happen. The reason I am asking is because I can't replicate this bug so I am kind of implementing a fail recovery solution.

    The error I get is on a TList object: "[EListError] List index out of bounds (0)". The TList contains few TForm objects where we made them invisible then add them to the TList right after that action. Now we want to make them visible again and free and nil the TList after that. Error happens when we want to make the forms visible again.

    So there's a loop and the TList.Count has a value. The code gets into loop and the above error happens. Isn't above error implies that there's no item at the specific index but the list count is greater than zero, how could this be?

    The only out of ordinary thing here might be the for loop counting down so that we display the forms in reverse order.

    for ii := FormListObject.Count - 1 downto 0 do begin
       // Error happens here
       TForm(FormListObject[ii]).Show;
    end;
    

    Do you think this is a gui threading issue, a child item issue or somehow one of the forms got destroyed/killed and the list has a dead reference? Still I thought this error meant that there's no TList item at index 0, dead reference should trigger an access violation error, no?

  • Alex
    Alex about 10 years
    Thank you for your answer. Well I have a stack trace, and I already know where the error happens, which list it is and why it happens (there's an empty list). I just can't replicate this rare bug my side. Something causes a TForm item in my list to disappear while the list count is retained. The code is pretty straight forward, add items to the list, loop items in the list and kill the list. Error happens in the loop, without access violations. The key point here is I think that why would something that cause an item(s) to be removed from the list does not decrease the list count?
  • mghie
    mghie about 10 years
    @Alex: The list count will be evaluated only at the start of the loop. Removing items from the list during the loop will result in the error you're seeing.
  • Alex
    Alex about 10 years
    @mghie There're no items removed from the list by the code explicitly in the loop. I've edited my post above to show how simple this loop is. The list is also not cleared or modified anywhere where else in this unit. Well the only location is where it's populated after list creation. List is destroyed right after the loop I have the bug.
  • mghie
    mghie about 10 years
    @Alex: great you found the bug - it's probably nothing that "causes an item(s) to be removed from the list does not decrease the list count"? If so I would indeed be interested to hear about it.
  • David Heffernan
    David Heffernan about 10 years
    Clearly something is removing items from the list.
  • Alex
    Alex about 10 years
    I've asked this question here to get some ideas about what can cause such a thing. I'll need further investigation and perhaps use logging. I'll keep all these ideas in mind too. Thanks