Looping over the children of an empty Boost.PropertyTree is usually a no-op:
ptree empty;
for (auto const& elements : empty)
{
std::cout << "child\n"; // Executed 0 times, as expected
}
but sometimes it crashes with an access violation :
ptree empty;
for (auto const& elements : empty.get_child("non-existent", ptree{})))
{
std::cout << "child\n";
}
Access violation reading location 0xFFFFFFFFFFFFFFFF.
(Inside
basic_ptree<K, D, C>::begin() const
)
Now obviously empty
has no child "non-existent", but there's a default value provided (ptree{}
). We know from the first example that it's OK to loop over an empty collection.
The usual way to detect a read failure does not work as this is an Access Violation / Undefined Behavior inside Boost.PropertyTree.
How can you distinguish between the first and second type of empty property trees, so you can avoid iterating over the type that blows up?
The problem is that Boost.PropertyTree takes that default (a temporary) by const reference. And the temporary dies immediately, even before begin
is called on it.
You can't detect this problem at runtime. The workaround is to have a non-temporary empty ptree
to use as a default. This can be a const ptree
so you can share it between different calls. Another solution is to use this trick.