[Boost.Format] empty string argument causes VC 8.0 to assert

The following code causes a runtime assertion in VC 8.0: std::string l_param; std::string l_str = (boost::format("here is an empty string: %1%") % l_param).str(); It passes an empty string argument to boost::format. The assert is inside the implementation of basic_string::append() and boils down to the fact that the implementation of boost::format ends up calling basic_string::append(const char *, size_type) with a null pointer, which causes basic_string::append to assert. The following sample code causes the same assertion without boost::format being involved: std::string l_str; const char *l_null = NULL; std::string::size_type l_size = 0; l_str.append(l_null, l_size); // causes an assert I have currently disabled the assertion by calling the following code before I do anything else: #if _MSC_VER >= 1400 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); #endif which causes the asserts to simply emit a message to stderr rather than to pop up a message box, but I don't really want to disable VC 8.0's assertions across the board. My questions are: 1) Is this considered to be a bug in boost::format or a case of VC 8.0's runtime checks being overzealous? Personally I feel that calling append(null, 0) should be allowed and VC 8.0 is being too protective, but the copy of the C++ standard I have suggests that VC 8.0 is correct. 2) Either way, what do people think is the best way forward? thanks, mick

At 04:34 2005-11-28, Mick Hollins wrote:
The following code causes a runtime assertion in VC 8.0:
std::string l_param; std::string l_str = (boost::format("here is an empty string: %1%") % l_param).str();
It passes an empty string argument to boost::format. The assert is inside the implementation of basic_string::append() and boils down to the fact that the implementation of boost::format ends up calling basic_string::append(const char *, size_type) with a null pointer, which causes basic_string::append to assert.
The following sample code causes the same assertion without boost::format being involved:
std::string l_str; const char *l_null = NULL; std::string::size_type l_size = 0; l_str.append(l_null, l_size); // causes an assert
I have currently disabled the assertion by calling the following code before I do anything else:
#if _MSC_VER >= 1400 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); #endif
which causes the asserts to simply emit a message to stderr rather than to pop up a message box, but I don't really want to disable VC 8.0's assertions across the board.
My questions are:
1) Is this considered to be a bug in boost::format or a case of VC 8.0's runtime checks being overzealous? Personally I feel that calling append(null, 0) should be allowed and VC 8.0 is being too protective, but the copy of the C++ standard I have suggests that VC 8.0 is correct.
I've been dismayed since I started using (std::)string that (std::)string blah((char*)0); didn't work. I'm not surprised that std::string::append suffers the same way.
2) Either way, what do people think is the best way forward?
thanks, mick
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

On 11/28/05, Mick Hollins
The following code causes a runtime assertion in VC 8.0:
std::string l_param; std::string l_str = (boost::format("here is an empty string: %1%") % l_param).str();
It passes an empty string argument to boost::format. The assert is inside the implementation of basic_string::append() and boils down to the fact that the implementation of boost::format ends up calling basic_string::append(const char *, size_type) with a null pointer, which causes basic_string::append to assert.
::_Inside(const char * _Ptr=0x00000000) Line 2023 + 0x13 bytes C++ msvcp80d.dll!std::basic_string
& res="", const char * beg=0x00000000, unsigned int size=0, int w=0, const char fill_char=' ', int f=513, const char prefix_space=0, bool
This assertion seems to only happen with /MDd (e.g. debug runtime), but I'd
say it qualifies as a bug in Boost.Format.
Here's the stack trace:
msvcp80d.dll!std::_Debug_message(const wchar_t * message=0x105157a0,
const wchar_t * file=0x10514a0c, unsigned int line=2023) Line 23 C++
msvcp80d.dll!std::_Debug_pointer<char>(const char * _First=0x00000000,
const wchar_t * _File=0x10514a0c, unsigned int _Line=2023) Line 1334 + 0x12
bytes C++
msvcp80d.dll!std::basic_string const &>(const
std::basic_string (const std::basic_string And here's the offending code from boost::io::detail::mk_str
(feed_args.hpp):
typedef typename std::basic_string

Caleb Epstein wrote:
On 11/28/05, *Mick Hollins*
mailto:mick@hollins.id.au> wrote: The following code causes a runtime assertion in VC 8.0:
std::string l_param; std::string l_str = (boost::format("here is an empty string: %1%") % l_param).str();
It passes an empty string argument to boost::format. The assert is inside the implementation of basic_string::append() and boils down to the fact that the implementation of boost::format ends up calling basic_string::append(const char *, size_type) with a null pointer, which causes basic_string::append to assert.
This assertion seems to only happen with /MDd (e.g. debug runtime), but I'd say it qualifies as a bug in Boost.Format.
yes I agree.
And here's the offending code from boost::io::detail::mk_str (feed_args.hpp):
typedef typename std::basic_string
::size_type size_type; res.resize(0); if(w<=0 || static_cast (w) <=size) { // no need to pad. res.reserve(size + !!prefix_space); if(prefix_space) res.append(1, prefix_space); => res.append(beg, size); } I think the simple and obvious fix is to just check for size != 0 before calling res.append, but I'm not familiar with this code.
Yep that seems like the obvious fix. I've not yet been involved in contributing to boost, but am happy to do so, so I'm gonna read up on exactly how one goes about getting a change into the base and go from there. I presume there's doco somewhere on the boost site that tells me how to get started ... cheers, mick
participants (3)
-
Caleb Epstein
-
Mick Hollins
-
Victor A. Wagner Jr.