Opened 14 years ago

Closed 13 years ago

#2295 closed Bugs (fixed)

Inconsistent behavior when using 64 bit integer types

Reported by: Hrvoje Prgeša <hrvoje.prgesa@…> Owned by: nasonov
Milestone: To Be Determined Component: lexical_cast
Version: Boost 1.36.0 Severity: Problem
Keywords: lexical_cast 64 uint64_t int64_t Cc:

Description

1) Converting 64bit unsigned int to it's max value string representation and back results in exception (should be identity operation!):

boost::uint64_t max = numeric_limits<boost::uint64_t>::max();
std::string s = lexical_cast<string>(max);
BOOST_CHECK_EQUAL(max, lexical_cast<boost::uint64_t>(s));
// crashes: std::bad_cast: bad lexical cast: source type value could not be interpreted as target

2) Precise conditions when the conversion will fail are not specified in the documentation. Throwing of bad_lexical_cast is inconsistent:

#define T short
// add a digit to a min representation!
s = lexical_cast<string, T>(numeric_limits<T>::min()) + "0";
BOOST_CHECK_THROW(lexical_cast<T>(s), boost::exception); // throws
s = lexical_cast<string, T>(numeric_limits<T>::min()) + "5";
BOOST_CHECK_THROW(lexical_cast<T>(s), boost::exception); // throws

#define T boost::int64_t
s = lexical_cast<string, T>(numeric_limits<T>::min()) + "0";
BOOST_CHECK_THROW(lexical_cast<T>(s), boost::exception); // DOES NOT throw!?!?
s = lexical_cast<string, T>(numeric_limits<T>::min()) + "5";
BOOST_CHECK_THROW(lexical_cast<T>(s), boost::exception); // throws  

Change History (5)

comment:1 by Hrvoje Prgeša <hrvoje.prgesa@…>, 14 years ago

Note: tested on MS VC9 (without SP1)

comment:2 by anonymous, 14 years ago

Update: the 2. problem seems to be caused by the MSVC streams bug, and the 1. might also probably caused by it.

Nevertheless, lexical_cast tests really should include tests for 64bit integer types.

comment:3 by nasonov, 14 years ago

Nevertheless, lexical_cast tests really should include tests for 64bit integer types.

They do. Search for LCAST_TEST_LONGLONG in http://svn.boost.org/svn/boost/branches/release/libs/conversion/lexical_cast_test.cpp

Though, I don't understand/remember why it uses int64 rather than boost::long_long_type.

I should also add a test for boost::intmax_t type.

in reply to:  3 comment:4 by anonymous, 14 years ago

Replying to nasonov:

Nevertheless, lexical_cast tests really should include tests for 64bit integer types.

They do. Search for LCAST_TEST_LONGLONG in http://svn.boost.org/svn/boost/branches/release/libs/conversion/lexical_cast_test.cpp

They do indeed. Didn't notice it before when I was looking.

Though, I don't understand/remember why it uses int64 rather than boost::long_long_type.

The link you posted tests boost::long_long_type if BOOST_HAS_LONG_LONG is defined (and seems fall back on int64 defending on few other defined).

I should also add a test for boost::intmax_t type.

May I suggest adding more tests that check conversion failure in the generic testing routines - there is currently not a single one failure test in them (and therefore not a single failure test for long long), there are only tests for around min, max, 0 and exp(10).

Eg. for "test_conversion_from_integral_to_string" something like my second use case would fit nicely: typedef std::basic_string<CharT> string_type; for(i = 0; i <= 10; ++i) {

string_type underflow_str = to_str<CharT>(limits::min()) + to_str<CharT>(i); BOOST_CHECK_THROW(lexical_cast<T>(underflow_str), bad_lexical_cast);

string_type overflow_str = to_str<CharT>(limits::max()) + to_str<CharT>(i); BOOST_CHECK_THROW(lexical_cast<T>(overflow_str), bad_lexical_cast);

} (this check overflow and underflow by appending digits, not by strictly increasing the min/max by +/-1, although that could also be done.)

comment:5 by nasonov, 13 years ago

Resolution: fixed
Status: newclosed

(In [56170]) Fix #2295 (Inconsistent behavior when using 64 bit integer types).

Note: See TracTickets for help on using tickets.