boost compiles differently, if ACE header is included first

Hello, I have a little problem regarding boost and ACE cooperation. ACE is an C++ class library, providing many functions for platform independency. I have also reported this to the debian team, and will also try to contact the ACE developers: Package: libboost-dev Version: 1.32.0-6 Package: libace-dev Version: 5.4.2.1.0-4 Consider the following program boostfirst.cpp: ------------------------------------------------------------ #include <boost/shared_ptr.hpp> #include <ace/OS.h> #include <iostream> using namespace std; int main (int argc, char **argv) { cout << "sizeof (boost::detail::sp_counted_base) == " << sizeof (boost::detail::sp_counted_base) << endl; } ------------------------------------------------------------ Compile and run with: $ g++ boostfirst.cpp -o boostfirst -lstd $ ./boostfirst sizeof (boost::detail::sp_counted_base) == 12 Now try including the ace header first (only the order of the include files is changed): ------------------------------------------------------------ #include <ace/OS.h> #include <boost/shared_ptr.hpp> #include <iostream> using namespace std; int main (int argc, char **argv) { cout << "sizeof (boost::detail::sp_counted_base) == " << sizeof (boost::detail::sp_counted_base) << endl; } ------------------------------------------------------------ The output of the second program is: sizeof (boost::detail::sp_counted_base) == 36 A great difference. The reason for this is, that the #include <ace/OS.h> somehow defines _REENTRANT, which triggers the boost library to include a mutex in sp_counted_base. I think, the order of the includes should not matter. Therefore, either '#include <ace/OS.h>' should not define _REENTRANT, or the boost headers should ignore it. I found out, that adding the -pthread option to the g++ command also avoids this bug. Im using Debian sarge 3.1, g++ 3.3.5-3, libc6 2.3.2.ds1-22sarge3 and libace-dev 5.4.2.1.0-4. Regards, Torsten

Harling, Torsten wrote: [...]
Now try including the ace header first (only the order of the include files is changed): ------------------------------------------------------------ #include <ace/OS.h> #include <boost/shared_ptr.hpp> #include <iostream>
using namespace std;
int main (int argc, char **argv) { cout << "sizeof (boost::detail::sp_counted_base) == " << sizeof (boost::detail::sp_counted_base) << endl; } ------------------------------------------------------------
The output of the second program is: sizeof (boost::detail::sp_counted_base) == 36
A great difference. The reason for this is, that the #include <ace/OS.h> somehow defines _REENTRANT, which triggers the boost library to include a mutex in sp_counted_base. I think, the order of the includes should not matter. Therefore, either '#include <ace/OS.h>' should not define _REENTRANT, or the boost headers should ignore it.
I found out, that adding the -pthread option to the g++ command also avoids this bug.
If you compile #include <boost/shared_ptr.hpp> #include <iostream> using namespace std; int main (int argc, char **argv) { cout << "sizeof (boost::detail::sp_counted_base) == " << sizeof (boost::detail::sp_counted_base) << endl; } (same program without the ACE include) you'll probably get the expected outcome of 12 when -pthread isn't used and 36 when -pthread is used. This is likely caused by g++ -pthread defining _REENTRANT, which is then used by boost/config.hpp to enable threading support. Since <boost/shared_ptr.hpp> doesn't know whether you're going to include an ACE header afterwards, it has to decide whether to include a mutex based on the present settings. If we make it ignore _REENTRANT, the above program will revert to single-threaded mode even when -pthread is used, and this is likely to break code. The only practical solution seems to be to consistently use -pthread with ACE, as I don't expect the ACE headers to stop defining _REENTRANT. They probably have their own reasons for that and they don't need to support single-threaded code.

Hi Torsten, On 7/26/06, Harling, Torsten <THarling@arri.de> wrote:
Hello,
I have a little problem regarding boost and ACE cooperation. ACE is an C++ class library, providing many functions for platform independency. [snip] A great difference. The reason for this is, that the #include <ace/OS.h> somehow defines _REENTRANT, which triggers the boost library to include a mutex in sp_counted_base. I think, the order of the includes should not matter. Therefore, either '#include <ace/OS.h>' should not define _REENTRANT, or the boost headers should ignore it. [snip]
ACE requires you to use multithreading in most cases. I seriously doubt that this will be seen as a bug by anybody you've reported to, as this is just how ACE works. In this case, sp_counted_base is doing the right thing, as it sees that it needs to be threadsafe. I would strongly recommend that you ensure that you use the same compilation flags and defines to build your software as you did when building ACE, otherwise you may just end up with different versions of the same class all over the place. Michael

On Wed, 26 Jul 2006 13:54:43 +0200 "Michael van der Westhuizen" <r1mikey@gmail.com> wrote:
ACE requires you to use multithreading in most cases. I seriously
Having used ACE for many years (including large amounts of current production software), I can say that this is not the case. It does not make it EASY, but it is not a requirement either. You can build anything from ACE with single or multi threading. The problem is that the configurations are way too complex, and depend on manual settings for the most part... it SHOULD use configure or the like (they are working on it... it is getting better). The real problem is that neither ACE nor boost handle MT issues appropriately (both end up assuming that all libs handle MT the same way, without providing much flexibility). config-macros.h... # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) # define ACE_MT(X) X # if !defined (_REENTRANT) # define _REENTRANT # endif /* _REENTRANT */ # else # define ACE_MT(X) # endif /* ACE_MT_SAFE */ so, if ACE_MT_SAFE is defined, you automatically get _REENTRANT. and in config-linux.h... #if !defined (ACE_MT_SAFE) #define ACE_MT_SAFE 1 // JCEJ 12/22/96 ##1 endif However, if you build with ACE's makefiles, wrapper_macros.GNU checks the environment to see if threads are enabled for your build, and if you are not building with threads enabled, it adds the following compiler flag 'ACE_MT_SAFE=0' Here, at ATD, we mix BOOST and ACE in just about everything we do. However, all our code is built using a set of build tools which, in the end, suck in the ACE configuration makefiles. We build boost, and our makefiles know how to figure out which variant of boost libraries to link against, based on the compilation options. I hope that helps... at least a little '-)

On 7/26/06, Michael van der Westhuizen <r1mikey@gmail.com> wrote:
Hi Torsten,
[snipped]
ACE requires you to use multithreading in most cases. I seriously doubt that this will be seen as a bug by anybody you've reported to, as this is just how ACE works.
I believe it should be reported as a bug to ACE. The ACE library should emit an error if _REENTRANT is not defined, not define it. As we can see it can lead to serious ODR violations, with part of the headers being preprocessed with and without _REENTRANT.
In this case, sp_counted_base is doing the right thing, as it sees that it needs to be threadsafe.
I would strongly recommend that you ensure that you use the same compilation flags and defines to build your software as you did when building ACE, otherwise you may just end up with different versions of the same class all over the place.
ditto.
Michael
best regards, -- Felipe Magno de Almeida

Hi Michael, Michael van der Westhuizen <r1mikey@gmail.com> wrote:
ACE requires you to use multithreading in most cases.
Multithreading is default in Visual Studio 8.0 and it seems to me that would be default on many platforms soon. V. Salamakha --------------------------------- See the all-new, redesigned Yahoo.com. Check it out.
participants (6)
-
Felipe Magno de Almeida
-
Harling, Torsten
-
Jody Hagins
-
Michael van der Westhuizen
-
Peter Dimov
-
val salamakha