|
Boost Users : |
Subject: Re: [Boost-users] Serialization demo program crashes trying to free anunallocated block
From: Jean-Denis Muys (jdmuys_at_[hidden])
Date: 2009-09-20 14:40:23
Well, I spent a large number of hours since my original message, and
while I learned a lot, I could not solve my problem and I am about to
give up using Boost.
Here is what I managed to find out:
- first an foremost, the example works fine when compiled and run from
the terminal using the following command:
c++ demo.cpp -o demo /usr/local/lib/libboost_serialization.dylib
- the crash happens when running the example from the XCode IDE. Since
my real project is developed using XCode, this is a show-stopper.
- clearly, this is a Mac specific issue. I suspect something stupid,
such as a build setting or something, but I could not find what. I
posted requests for help on the XCode mailing list, but judging by the
suggestions I got, Boost is not very popular with Mac developers.
- So if somebody has managed to set up a working project under XCode
(version 3.2 preferably), I'd be really interested in that.
Now to the crash: I downloaded the source code the Mac version of the
standard C++ library and for its malloc/free routine. Using that, I
managed to reconstruct what's happening:
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, but a this point, I throw in the towel.
Jean-Denis
On Sep 20, 2009, at 21:04 , Robert Ramey wrote:
> I tried it on my system with both msvc-7.11 and gcc-4.3.2 (under
> cygwin)
> and it worked fine. I used bjam to build and test it.
>
> Robert Ramey
>
> Jean-Denis Muys wrote:
>> Hi,
>>
>> Warning: noob inside. I am new to boost, and quite a bit rusty with
>> C+
>> +, having spent the past few years with other languages.
>>
>> Nonetheless.
>>
>> I downloaded, built and installed Boost 1.40 just fine on Mac OS X
>> 10.6 (Snow Leopard).
>>
>> I set up a XCode 3.2 project to compile and run the demo.cpp program
>> delivered with the Serialization library.
>>
>> It crashes deep inside this line:
>>
>> restore_schedule(new_schedule, filename.c_str());
>>
>> GDB gives the following error message:
>>
>> malloc: *** error for object 0x1000581a0: pointer being freed was not
>> allocated
>>
>> The stack crawl shows:
>>
>> #0 0x7fff81202ff6 in __kill
>> #1 0x7fff812a4072 in abort
>> #2 0x7fff811bb095 in free
>> #3 0x7fff836031e8 in std::string::reserve
>> #4 0x7fff836032fe in std::string::append
>> #5 0x10028ccac in
>> boost
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net