Problem 802

Summary: G4MassGeometrySampler destructor calls already deallocated memory, segmentation failure
Product: Geant4 Reporter: mmarino
Component: processes/transportationAssignee: alexander.howard
Status: CLOSED REMIND    
Severity: normal    
Priority: P2    
Version: 7.1   
Hardware: All   
OS: All   

Description mmarino 2005-10-12 20:55:19 CEST
I have a program which constructs a G4MassGeometrySampler within a
G4VUserDetectorConstruction derived class (call it MyUDC). When I delete the
G4RunManager it calls in sequence
...
G4ParticleTable::GetParticleTable()->DeleteMessenger();
...
delete userDetector;

DeleteMessenger() deletes the entire particle table.  "delete userDetector"
calls MyUDC::~MyUDC which calls "delete mgs" (a G4MassGeometrySampler).

Tracing this I found that G4MassGeometrySampler::~G4MassGeometrySampler ->
G4MImportanceConfigurator::~G4MImportanceConfigurator() ->
G4ProcessPlacer::RemoveProcess(G4VProcess*) ->
G4ProcessPlacer::PrintPostStepGPILVec() -> G4ProcessPlacer::GetProcessManager().

This last function calls G4ParticleTable::GetParticleTable() which is already
gone.  There is no testing to determine whether the pointer to the Particle
Table actually receives a meaningful memory location.  I'm not exactly sure if
the segmentation error occurs within this function or within GetParticleTable()
.  If the ParticleTable doesn't exist, then GetProcessManager() should return
NULL which then should be dealt with appropriately by the calling functions.  If
it throws an exception, then it could kill a program trying to normally delete.

This problem is easily reproducible by adding the line
delete runManager;
right before the last curly brace into exampleB01.cc (in
examples/extended/biasing/B01/).  It turns out the issue is normally skirted in
exampleB01 because c++ automatically calls the destructors in the correct order
(i.e. G4MassGeometrySampler and then G4RunManager).
Comment 1 alexander.howard 2005-12-09 09:49:59 CET
problem occurs because the mass geometry sampler destructor does not get called
into it goes out of scope - program exits.  As the runManager has already
deleted the processes this causes the segmentation fault.  The fix is as follows:
Add the line:
    mgs.ClearSampling()
    delete runManager;

before the
    return 0;
at the end of the main program and everything closes properly.
The reason the particle table is not checked before deleting a process is that
processes are attached to particles, therefore to delete an abstract process
with no particle is meaningless.
I hope this also fixes the user's application code.