Subject: [Boost-bugs] [Boost C++ Libraries] #12578: Crash with boost::filesystem's directory_iterator and recursive_directory_iterator
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-11-03 19:08:29
#12578: Crash with boost::filesystem's directory_iterator and
recursive_directory_iterator
-----------------------+------------------------------
Reporter: anonymous | Type: Bugs
Status: new | Milestone: To Be Determined
Component: None | Version: Boost 1.61.0
Severity: Problem | Keywords:
-----------------------+------------------------------
I have a simple example using `recursive_directory_iterator` that crashes,
but it also crashes with `directory_iterator`. I am aware from the
documentation that "[t]he practical consequence of not preserving equality
is that directory iterators can only be used for single-pass algorithms",
but I don't see why my use here would invoke undefined behavior since I
make a copy of a `const` iterator.
{{{
#!div style="font-size: 80%"
{{{#!cpp
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
namespace fs = boost::filesystem;
int main()
{
try
{
const auto iter = fs::recursive_directory_iterator{ "." };
std::cout << std::distance( iter, {} ) << "\n";
for( const auto& entry : boost::make_iterator_range(
iter, // CRASH!
{} ) )
{
std::cout << entry << "\n";
}
}
catch( const std::exception& e )
{
std::cerr << e.what() << "\n";
}
catch( ... )
{
std::cerr << "Unknown exception.\n";
}
}
}}}
}}}
This crashes on several compilers, Windows and Linux, and multiple
versions of Boost.^[#crash (a)]^
Note that `iter` is `const`. I can workaround this by (1) replacing
`iter```^[#replaceIter (b)]^ on the line marked "CRASH" with
`fs::recursive_directory_iterator{ "." }` or (2) deleting the call to
`std::distance()` just before the for loop or by changing its
arguments^[#replaceDist (c)]^. Either of these have the effect of not
advancing a copy of `iter` to the end.
I suspect this has something to do with the copy of `iter` made by
`std::distance()` and `boost::make_iterator_range()` still being secretly
connected to the internal state of `iter`, though it is a `const` iterator
from which a deep copy was supposed to be made. It also happens with
experimental::filesystem^[#expFS (d)]^ and multiple versions of Boost (at
least 1.61.0 and 1.55.0).
This same problem can also be seen in other scenarios such as iterating
over a directory range twice^[#twice (e)]^ or any other use of a recursive
directory iterator which has had a copy made and advanced to end.
I asked about this on the Boost Users list^[#user (f)]^, but got no reply.
'''Links'''
* [=#crash (a)] See, e.g., the crash on Coliru with gcc: coliru.stacked-
crooked.com/a/15c4a731100d25f2
* [=#replaceIter (b)] coliru.stacked-crooked.com/a/b37f94ebc809fa65
* [=#replaceDist (c)] coliru.stacked-crooked.com/a/17277df962ab5989
* [=#expFS (d)] coliru.stacked-crooked.com/a/8e83f5c7e2adfe90
* [=#twice (e)] coliru.stacked-crooked.com/a/0bfab95a513ebed8
* [=#user (f)] lists.boost.org/boost-users/2016/10/86840.php
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/12578> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:20 UTC