Boost logo

Boost Users :

From: Rush Manbert (rush_at_[hidden])
Date: 2005-08-04 14:43:57

Hi all,

I am writing all of this down because I was only able to find cryptic
references to this problem in the Boost archives, and in the Apple
Xcode-Users archives. I also want to ask whether my solution to the
problem makes sense.

I am developing a cross platform static library on OSX 10.4.2 using
Xcode 2.1. The Xcode IDE includes a mechanism for unit testing that I am
using. The unit test target is setup by Xcode, and one of the things it
does is to include Carbon.h as a "prefix include". This means that the
compiler command line includes "-include <path>/Carbon.h" and this
header file is read BEFORE anything else.

Everything had been going great until I wrote a test using
boost::shared_ptr. I began to see all sorts of strange behaviors. After
a while I turned on Guard Malloc in the debugger. That was when it
started catching bad access errors in pthread_mutex_init, which was
being called as a result of creating a boost:shared_ptr. It turns out
that in the constructor for:
    template<class P, class D> shared_count(P p, D d)
 it executes this:
    pi_ = new sp_counted_base_impl<P, D>(p, d);

Class sp_counted_base_impl is derived from sp_counted_base, and
sp_counted_base has a data member declared as:
#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
    mutable mutex_type mtx_;

In the constructor for sp_counted_base, the constructor for mutex_type
(lightweight_mutex) was being called. It in turn called
pthread_mutex_init, passing the address of its mutex member, which is a
44 byte buffer.

The memory access problem, though, is that when operator new called
malloc, it did so as if sp_counted_base did NOT contain the mutex data
member. This means that the 44 byte buffer wasn't allocated, and because
Guard Malloc is very clever, the access outside of the allocated space
was caught.

I searched around and found messages where people said they saw problems
like this because the Carbon headers were included before the Boost
headers. This certainly fit my situation. I managed to change the order
of header inclusion and everything started working. The class memory was
allocated including space for mtx_ and the mutex init worked. This is
really a lousy solution, though, so I kept poking around.

I put things back so that Carbon.h was included on the command line, and
assumed I would need to live with that. I added -DBOOST_HAS_THREADS to
my compiler flags. The test still failed because the mutex memory had
not been allocated. Because of this, I looked for anywhere where
BOOST_HAS_THREADS could be #undef-ed. I found two possibilities, both in
boost/config/suffix.hpp. It appeared that in my case BOOST_HAS_PTHREADS
was not defined. This led me to boost/config/macos.hpp. I found this
little code snippet:

// BSD runtime has pthreads, sigaction, sched_yield and gettimeofday,
// of these only pthreads are advertised in <unistd.h>, so set the
// other options explicitly:

I tried including <unistd.h> ahead of shared_ptr.hpp, but that still
failed the same way.

I edited macos.hpp and added a fourth #define to this section:

When I built with the modified header, everything worked as expected.
The mutex space was allocated. I don't want to change the Boost headers,
though, so undid the change to macos.hpp. I went back to my test target
in Xcode and changed the compiler flag -DBOOST_HAS_THREADS to
-DBOOST_HAS_PTHREADS. I rebuilt my test code and everything works perfectly.

So it *appears* that defining BOOST_HAS_PTHREADS on the compiler command
line is the general case solution for this problem, but I'm looking for
opinions more expert than mine. If this is indeed true, then does anyone
know why the macro isn't just defined in
boost/config/platform/macos.hpp? Have I opened myself up to other
problems by doing this? Any help would be appreciated.

- Rush

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at