On RHEL7.4, boost 1.53,
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
int main() {
const string& s1 = "1024";
cout << "test1:" << lexical_cast<unsigned int>(s1) << endl;
filesystem::path p("1024");
cout << "test2:" << lexical_cast<unsigned int>(p.filename().string()) << endl;
const string& s2 = p.filename().string();
cout << "test3:" << lexical_cast<unsigned int>(s2) << endl;
return 0;
}
This code gives:
test1:1024
test2:1024
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_lexical_cast> >'
what(): bad lexical cast: source type value could not be interpreted as target
zsh: abort ./a.out
Maybe this is a lexical_cast's bug but someones knows why test3 fails? Especially, I can't understand different between test1 and 3.
This line creates a dangling reference:
const string& s2 = p.filename().string();
That's because on POSIX systems, path::filename() returns a reference to a member(!!!). Therefore, no lifetime extension occurs, as would have been if it had returned a temporary.
Now, because filename() returns a temporary path() the reference is no longer valid. Your program invokes Undefined Behaviour.
I'd suggest a fix like:
p = p.filename();
const string& s2 = p.string();
cout << "test3:" << lexical_cast<unsigned int>(s2) << endl;
Or
p = p.filename();
cout << "test3:" << lexical_cast<unsigned int>(p.string()) << endl;
Or even
cout << "test3:" << lexical_cast<unsigned int>(p.filename().string()) << endl;
Best of all would be to keep things simple:
std::string const s2 = p.filename().string();
cout << "test3:" << lexical_cast<unsigned int>(s2) << endl;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With