Problem 947

Summary: Code error in G4ExcitationHandler.cc
Product: Geant4 Reporter: Tom Roberts <tjrob>
Component: processes/hadronic/models/de_excitation/handlerAssignee: alexander.howard
Status: RESOLVED FIXED    
Severity: major CC: alexander.howard, porosev
Priority: P5    
Version: 8.3   
Hardware: All   
OS: All   

Description Tom Roberts 2007-05-15 19:12:53 CEST
On WIN32-VC, the following coding error generates a General Protection Fault by attempting to dereference a null pointer within the STL::list<> class. This is a VERY flaky problem, and only appears occasionally for some simulations, and not at all for others.

File G4ExcitationHandler.cc (loop at line 215):

    std::list<G4Fragment*>::iterator j;
    for (j = theResultList.begin(); j != theResultList.end(); j++) {
        if( /* some test */) {
            // some code
            delete(*j);
            theResultList.erase(j--);
            // some code not using j
        } else {
            // some code that uses j
        }
    }

Clearly j can be decremented to point "previous" to begin(), which is undefined. Apparently on gcc it is OK (well, does not generate a fault, but I have no idea if it runs correctly). On Windows, VC++ generates a fault, at least if the list becomes empty from the erase().

This avoids the fault, BUT CHANGES THE LOGIC:
            // replace the above delete and erase() with:
            theResultList.erase(j);
            delete *j;
            if(theResultList.size() == 0) break;
            j--;

While that permits my simulation to execute, I believe it can omit generating some secondaries, so an expert on this process needs to look at it. I recommend changing that std::list<> to a std::vector<> and using an integer to index the vector -- an integer can be validly decremented to point before the start and then incremented before next use; an iterator cannot.

NOTE -- on WIN32-VC you must also implement the workaround to the compiler bug I reported in the "Installation and Configuration" forum thread 865.
Comment 1 alexander.howard 2007-05-16 09:01:24 CEST
Could you include a description of the situation which reproduces this problem - there are a number of possible fixes but we should verify that it's successful.
Thanks,
Alex
Comment 2 Tom Roberts 2007-05-16 15:55:01 CEST
This occurs when tracking charged particles through matter, running wih G4SYSTEM=WIN32-VC. This routine is called by photon evaporation.

This is stochastic: several of my simulations run 10,000 events without crashing. One simulation crashes on event # 5, but not again until some event # > 1000 -- this simulation has 10 GeV/c protons entering a carbon target 50 mm in radius and 1,000 mm long; the target is along the axis of a 20 T solenoid; physics=QGSP_BIC.

This _is_ a clear coding error: decrementing a std::list<>::iterator from begin() is documented as undefined behavior. Apparently g++ does something different from VC++, as it does not crash on any of my simulations, for G4SYSTEM =  Linux-g++, Darwin-g++, or Windows-g++. Note, however, that I have NOT verified that with g++ it executes the loop correctly, just that it does not crash.

Note that I am really using Geant4.8.2, but this file is unchanged in 8.3, so I reported the bug in the latter release.
Comment 3 alexander.howard 2007-05-16 18:28:02 CEST
*** Problem 944 has been marked as a duplicate of this problem. ***
Comment 4 alexander.howard 2007-06-13 08:11:24 CEST
This code is now corrected and will be in Geant4 release 9.0 (end of June 2007). Can be supplied if required before.