On 11/28/05, Mick Hollins <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.
::_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
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>
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.
--
Caleb Epstein
caleb dot epstein at gmail dot com