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.
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<char,std::char_traits<char>,std::allocator<char> >::_Inside(const char * _Ptr=0x00000000) Line 2023 + 0x13 bytes C++
msvcp80d.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::append(const char * _Ptr=0x00000000, unsigned int _Count=0) Line 942 + 0xc bytes C++
> format.exe!boost::io::detail::mk_str<char,std::char_traits<char>,std::allocator<char> >(std::basic_string<char,std::char_traits<char>,std::allocator<char> > & 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 center=false) Line 50 C++
format.exe!boost::io::detail::put<char,std::char_traits<char>,std::allocator<char>,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const &>(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & x="", const boost::io::detail::format_item<char,std::char_traits<char>,std::allocator<char> > & specs={...}, std::basic_string<char,std::char_traits<char>,std::allocator<char> > & res="", boost::io::basic_altstringbuf<char,std::char_traits<char>,std::allocator<char> > & buf={...}, std::locale * loc_p=0x00000000) Line 161 + 0x3b bytes C++
format.exe!boost::io::detail::distribute<char,std::char_traits<char>,std::allocator<char>,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const &>(boost::basic_format<char,std::char_traits<char>,std::allocator<char> > & self={...}, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & x="") Line 242 + 0x3f bytes C++
format.exe!boost::io::detail::feed<char,std::char_traits<char>,std::allocator<char>,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const &>(boost::basic_format<char,std::char_traits<char>,std::allocator<char> > & self={...}, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & x="") Line 251 + 0xd bytes C++
format.exe!boost::basic_format<char,std::char_traits<char>,std::allocator<char> >::operator%<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & x="") Line 64 + 0xd bytes C++
format.exe!main() Line 13 + 0x35 bytes C++
format.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C
format.exe!mainCRTStartup() Line 403 C
KERNEL32.DLL!ProcessIdToSessionId() + 0x17d bytes
[Frames below may be incorrect and/or missing, no symbols loaded for KERNEL32.DLL]
And here's the offending code from boost::io::detail::mk_str (feed_args.hpp):
typedef typename std::basic_string<Ch,Tr,Alloc>::size_type size_type; res.resize(0);
if(w<=0 || static_cast<size_type>(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.