[dune-fem] Bug in jacobianAll

Martin Nolte nolte at mathematik.uni-freiburg.de
Thu Mar 5 21:34:50 CET 2015


Hi Marco,

On 03/05/2015 12:45 PM, Agnese, Marco wrote:
> Hi Martin,
>
>> Well, with the copyable entities, writing *entityIterator _and_ then storing a
>> reference to its result is the only true source of segfaults I know of. In
>> itself, both operations are ok, but they may not be combined.
>
> I don't understand why.
> I mean dereferencing an iterator gives you an entity and simply you pass the reference to that entity to the method.
> Am I missing something?

This is a tricky one. There is a new feature in dune-grid: Iterators no longer 
have to return a reference to the entity they are pointing. Instead they may 
return a copy of the entity object. GeometryGrid, for example, uses this feature 
already. Now, if you dereference the iterator, you get a newly created temporary 
entity object. Now assume you write something like:

LocalFunction lf = df.localFunction( *it );

This passes a reference to the temporary entity object (*it) to the 
localFunction lf, which stores this reference internally (in the 
BasisFunctionSet). Now, C++ storage rule imply that the temporary object (*it) 
may be destructed after the statement has been executed (i.e., after the 
semicolon). From now on, lf contains a dangling reference. Note that newer 
versions of gcc agressivly use this possibility to optimize the generated code.

Now, things are completely different if you write

const Entity &e = *it;
LocalFunction lf = df.localFunction( e );

In this case, the temporary returned by (*it) is destructed at the end of the 
enclosing block, where all local variables include lf are destroyed. The reason 
for this behavior is that you named the temporary (here: 'e'). As a result, 
there is no dangling reference. Note that, if the iterator returns the entity by 
value, it does not make a notable difference whether you write

const Entity &e = *it;

or

const Entity e = *it;

A new copy of the entity is constructed either way (there might be a small 
difference in performance for some grids overloading the copy constructor, though).

I have to admit that you really have to read the C++ standard to realize this 
subtle difference. Unfortunately, it would require sophisticated C++ magic to 
warn you against this pitfall. Such problems are actually the reason why I would 
have preferred the hard break in compatibility.

For the time being, I can only urge people to name the entity before passing it 
on. This gives you basically the same lifetime guarantees you had before when 
the entity was actually stored in the iterator (I know of no grid implementation 
that ever kept all entities in memory. Actually I do not even have a clue how to 
do that).

Best,

Martin

>
>> So: Stick to the paradigm we successfully used over the last years: First
>> defererence the entity iterator and store (a reference to) the entity. Then pass
>> this entity around and you're basically safe. Just make sure the entity lives
>> longer than any object (e.g., LocalFunction, LocalMatrix, etc.) associated to it.
>
> Yes, I did it :)
>
>> A nice side effect of range-based for loops is that you are automatically safe
>> as long as you don't propagate objects like LocalFunctions out of the loop
>> (which I have never seen in dune-fem).
>
> I have to start to use the range-based loop!
>
>> Should we put such information onto some FAQ list or into the release notes?
>
> I think that a note in the release notes would be useful and may save a lot of time since it is a tricky bug to spot.
>
> Best,
>
> Marco
> _______________________________________________
> dune-fem mailing list
> dune-fem at dune-project.org
> http://lists.dune-project.org/mailman/listinfo/dune-fem
>

-- 
Dr. Martin Nolte <nolte at mathematik.uni-freiburg.de>

Universität Freiburg                                   phone: +49-761-203-5630
Abteilung für angewandte Mathematik                    fax:   +49-761-203-5632
Hermann-Herder-Straße 10
79104 Freiburg, Germany




More information about the dune-fem mailing list