Problem 2019 - underflow in G4EMDataSet::FindLowerBound(G4double x, G4DataVector* values) in G4EMDataSet.cc
Summary: underflow in G4EMDataSet::FindLowerBound(G4double x, G4DataVector* values) in...
Status: RESOLVED LATER
Alias: None
Product: Geant4
Classification: Unclassified
Component: processes/electromagnetic/lowenergy (show other problems)
Version: 10.3
Hardware: PC Linux
: P4 normal
Assignee: Sebastien Incerti
URL:
Depends on:
Blocks:
 
Reported: 2017-12-13 15:31 CET by Patrick van Beek
Modified: 2018-01-28 23:11 CET (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this problem.
Description Patrick van Beek 2017-12-13 15:31:16 CET
Hey together,

I'm using the newest version of Geant4 (10.3 with newest patch). 

I experienced some random crashes of my simulation in the last time (it occurred very rarely, about in ever billionth event or so). So I began debugging.
Using gdb, I found that the crash always occurred in G4EMDataSet::FindLowerBound(G4double x, G4DataVector* values).

Since the crash was caused by a segmentation fault, the only problem I could think of was accessing the array incorrectly. 
So I decided to change the line 

if (x < (*values)[midBin]) upperBound = midBin - 1;  //should be line 502

to (since the G4DataVector is an std::vector): 

if (x < values.at(midBin)) upperBound = midBin - 1;

and recompiled Geant4 to see if I get an exception. And yes it was an outOfRange exception. The value of midBin was the result of an underflow, as I checked.

In my humble opinion, this problem occurs exactly when (x < values[0]) holds, because the logic in this function does not work for this case!
I used only the Livermore Physics list. I'm not sure if it is assumed, that values[0] is always 0 and this is just not true for Livermore lists, or if this also could happen with other lists. 

To fix the problem I changed the function to be:

size_t G4EMDataSet::FindLowerBound(G4double x, G4DataVector* values) const
{
auto it = std::lower_bound(values->begin(),values->end(),x);
int index = std::distance(values->begin(),it);
return index;
}

I know this is not elegant. But Using the standard library is safer than using own logic.

I did not experience any noticeable performance impact.


Greets,
Patrick
Comment 1 Sebastien Incerti 2017-12-13 16:47:41 CET
Dear Peter,

Thank you very much for your bug report.

Would you please have a way to reproduce this issue with one of our extended/electromagnetic examples, eg. using a dedicated macro file (with same particle, energy, material...) ?

Or send us a printout of data for which the issue occurs (like particle, energy, material ...)

Or would you have the possibility to send us your application ?

We would like to make sure that the issue is not originating from the database itself.

Thanks a lot,

Sebastien & Vladimir
Comment 2 Sebastien Incerti 2018-01-28 23:11:56 CET
No further details.