Re: C++ std::string.resize crashes in free
Re: C++ std::string.resize crashes in free
- Subject: Re: C++ std::string.resize crashes in free
- From: Jean-Denis Muys <email@hidden>
- Date: Sun, 20 Sep 2009 16:48:08 +0200
Thanks for the suggestion Howard, but that did not help.
After spending maybe two dozen hours trying to track this, I give up.
I may come back to it later... maybe. At this point I don't have the
time AND the skill set to go any deeper.
In the meantime, if anybody has Boost working within XCode, I'd be
glad to hear from them.
Here is what I was able to find out.
My initial hypothesis was wrong: the linker is doing fine thank you.
resize indeed calls append. I downloaded the source code for both the
standard C++ library and malloc/free to go through it. As far as I can
tell, the chain of event is the following:
1- Boost allocate a new object of the sample code class
bus_stop_corner. It's properly constructed, and its strings are
initialized to empty std::string
2- Before reading the text for the street1 std::string, Boost calls
std::string:resize() to size it to the correct length (11 in the
sample run).
3- resize() sees that the new size is larger than the previous size
(which was 0), and so calls std::string:append() to append some memory
at the end.
4- append() sees that the new length is larger than the old string
capacity and calls td::string:reserve()
5- reserve() clones the old string into a newly allocated larger
buffer, of the size requested, and then calls _M_dispose() on the old
buffer. Here is its source code:
template<typename _CharT, typename _Traits, typename _Alloc>
void
basic_string<_CharT, _Traits, _Alloc>::
reserve(size_type __res)
{
if (__res != this->capacity() || _M_rep()->_M_is_shared())
{
// Make sure we don't shrink below the current size
if (__res < this->size())
__res = this->size();
const allocator_type __a = get_allocator();
_CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
_M_rep()->_M_dispose(__a);
_M_data(__tmp);
}
}
6- _M_rep()->_M_dispose() calls _M_destroy()
7- _M_destroy() calls deallocate() (a method on the allocator) on the
_M_rep() buffer
8- deallocate() calls the standard operator delete on its argument.
void
deallocate(pointer __p, size_type)
{ ::operator delete(__p); }
9- delete calls the standard C routine free(), which is defined in
malloc.c:
void
free(void *ptr) {
malloc_zone_t *zone;
size_t size;
if (!ptr)
return;
zone = find_registered_zone(ptr, &size);
if (!zone) {
malloc_printf("*** error for object %p: pointer being freed was not
allocated\n"
"*** set a breakpoint in malloc_error_break to debug\n", ptr);
malloc_error_break();
if ((malloc_debug_flags & (SCALABLE_MALLOC_ABORT_ON_CORRUPTION|
SCALABLE_MALLOC_ABORT_ON_ERROR)))
abort();
} else if (zone->version >= 6 && zone->free_definite_size)
malloc_zone_free_definite_size(zone, ptr, size);
else
malloc_zone_free(zone, ptr);
}
10- the error occurs because free() cannot find the zone from which
the string buffer was allocated.
At this point I give up: I checked that the std::string whose buffer
is deallocated was indeed properly constructed, ie that its buffer was
allocated in a normal way:
pointer
allocate(size_type __n, const void* = 0)
{
if (__builtin_expect(__n > this->max_size(), false))
std::__throw_bad_alloc();
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
}
To go further I would need to get deep into the malloc implementation.
Since the same code is running fine when built from the terminal, I
suspect this would be fruitless.
I'm open to suggestions, as Boost offers quite a few nice libraries,
but according to google, Boost is not very popular on the Mac.
Jean-Denis
On Sep 20, 2009, at 1:30 , Howard Hinnant wrote:
Hello Jean-Denis,
I'm not sure if this is the problem or not, but here's the first
thing I would try:
In Xcode, edit "active target". Ensure that the configuration is
set to Debug. Search for "preprocessor". Under "Preprocessor
Macros" the following macros will be set:
GCC_PREPROCESSOR_DEFINITIONS = _GLIBCXX_DEBUG=1
_GLIBCXX_DEBUG_PEDANTIC=1. Erase them. Rebuild. See if that fixes
it.
-Howard
On Sep 19, 2009, at 6:41 PM, Jean-Denis Muys wrote:
Hello,
I'm facing a strange bug with some C++ sample code that only occurs
when running from XCode, so I hope this is the right place to look
for some help.
I just installed the Boost C++ library because I want to use its
serialization facility.
Boost version 1.40 built and installed just fine following their
instructions at http://www.boost.org/doc/libs/1_40_0/more/getting_started/unix-variants.html
The serialization demo program builds and runs just fine from the
terminal. I built it that way:
c++ demo.cpp -o demo /usr/local/lib/libboost_serialization.dylib
Now my real project is under XCode 3.2 (on Snow Leopard) so I
wanted to build and run the same demo program from XCode.
I set up a new project for a C++ tool in XCode, modified the header
search path to add /usr/local/include/, added
libboost_serialization.dylib, and it built without error.
However, it now breaks at runtime with the following error message
from GDB:
malloc: *** error for object 0x1000581c0: pointer being freed was
not allocated
*** set a breakpoint in malloc_error_break to debug
(BTW, I did set that breakpoint, but I don't know what to do next).
The stack crawl is the following:
#0 0x7fff81291b91 in malloc_error_break
#1 0x7fff811bb083 in free
#2 0x7fff836031e8 in std::string::reserve
#3 0x7fff836032fe in std::string::append
#4 0x100156cac in
boost
::archive::text_iarchive_impl<boost::archive::text_iarchive>::load
at text_iarchive_impl.ipp:55
#5 0x100024a0e in
boost
::archive
::load_access::load_primitive<boost::archive::text_iarchive,
std::string> at iserializer.hpp:109
#6 0x100024a33 in
boost
::archive
::detail::load_non_pointer_type<boost::archive::text_iarchive,
std::string>::load_primitive::invoke at iserializer.hpp:332
#7 0x100024a58 in
boost
::archive
::detail::load_non_pointer_type<boost::archive::text_iarchive,
std::string>::invoke at iserializer.hpp:417
#8 0x100024a7d in
boost::archive::load<boost::archive::text_iarchive, std::string> at
iserializer.hpp:542
#9 0x100024aae in
boost
::archive
::detail
::common_iarchive
<boost::archive::text_iarchive>::load_override<std::string> at
common_iarchive.hpp:61
#10 0x100024adb in
boost
::archive
::basic_text_iarchive
<boost::archive::text_iarchive>::load_override<std::string> at
basic_text_iarchive.hpp:62
#11 0x100024b09 in
boost
::archive
::text_iarchive_impl
<boost::archive::text_iarchive>::load_override<std::string> at
text_iarchive.hpp:66
#12 0x100024b3c in
boost
::archive
::detail
::interface_iarchive
<boost::archive::text_iarchive>::operator>><std::string> at
interface_iarchive.hpp:61
#13 0x100024b73 in
boost
::archive
::detail
::interface_iarchive
<boost::archive::text_iarchive>::operator&<std::string> at
interface_iarchive.hpp:68
#14 0x10002665e in
bus_stop_corner::serialize<boost::archive::text_iarchive> at
demo.cpp:123
The interesting part is frame #4, the last frame for which I have
the source code:
template<class Archive>
BOOST_ARCHIVE_DECL(void)
text_iarchive_impl<Archive>::load(std::string &s)
{
std::size_t size;
* this->This() >> size;
// skip separating space
is.get();
// borland de-allocator fixup
#if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
if(NULL != s.data())
#endif
s.resize(size); // <============== crash on this line
if(0 < size)
is.read(&(*s.begin()), size);
}
The crash happens on the call to std::string.resize. But now what I
don't get is why is the next stack frame in std::string::append and
not std::string::resize?
(note that at crash time, the string s is the empty string and size
== 11).
As far as I can see the problem is that the linker linked to
std::string::append instead of std::string::resize.
The only explanation I have is that maybe Boost was built in a way
that is incompatible with XCode.
So what does XCode do that's different from what the terminal c++
command does?
Has anyone been able to integrate Boost into an XCode project, ie
those parts of Boost that are more than only headers?
Any help appreciated as I a relative newbie here.
Jean-Denis
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden