boost::signals build and C++Builder 6 Pro in 1.29.0
I have built the boost::signals library with C++Builder 6 Pro Update 4
and am running into problems:
a) We tend to use double word alignment, not quad word (which is the
default in C++Builder). It appears that the libraries are built with
quad word, but the headers don't enforce this, so when I change the
options to double word (in our project) and try to construct a signal with
boost::signal0<void> s;
I get an access violation when constructing a signal (from line 266 of
shared_count.hpp) The call stack is
00417F3F __internal_malloc
00417DD8 __internal_malloc
00417539 ___org_malloc
00416EA2 ___org_new
004076E1 boost::detail::shared_count::shared_count(this=:0012FBB4,
p=:007F3928, d={ }, =:007F3928)
004063E3
boost::shared_ptrboost::signals::detail::signal_base_impl::shared_ptrboost::signals::detail::signal_base_impl(this=:0012FBB0,
p=:007F3928)
0040546D
boost::shared_ptrboost::signals::detail::signal_base_impl::resetboost::signals::detail::signal_base_impl(this=:0012FF70,
p=:007F3928)
00403F51
boost::signals::detail::signal_base::signal_base(this=:0012FF70,
comp=:0012FC24)
0040232E boost::signal0
::signal0
boost::function_base > (this=:0012FF70, c=:0012FC7C, comp=:0012FC74) 00401BF3 main(argc=1, argv=:007F21E4) 00420862 __startup
b) If I do use quad word alignment, then the object constructs
correctly, but when I connect a method to it with
void VoidFunc(void)
{
}
int main(int argc, char* argv[])
{
boost::signal0<void> s;
s.connect(&VoidFunc);
}
the program hangs. Turning on CodeGuard shows a similar problem to that
above. The object was allocated with a size of 12 bytes, but code is
trying to access byte 16 in the object (I guess this is a similar
alignment problem). The callstack is
0041E44E boost::counted_base::dispose(this=:00C04360)
00427203 boost::signals::detail::signal_base_impl::connect_slot
00404741 boost::signal0
::connect(this=:0012FF60, in_slot=:0012FDA8) 004026C5 main(argc=1, argv=:00C021E4) 00433802 __startup
It says the this pointer block is only 12 bytes long, but the code is trying to access byte 16. Do (or should) all the bost headers force alignment before all structures/classes and then restore the alignment afterwards? Currently, I have to link directly with the signals source code to get use the library. Has anything to do with this been changed in the builds of 1.30.0? Thanks Russell
On Monday 03 March 2003 05:57 am, Russell Hind wrote:
Do (or should) all the bost headers force alignment before all structures/classes and then restore the alignment afterwards?
I don't see any reason that the Boost headers should do this unless they require a certain alignment to operate (and this should never be the case).
Currently, I have to link directly with the signals source code to get use the library.
Has anything to do with this been changed in the builds of 1.30.0?
Not that I know of. I see that the Boost Jam toolset for Borland sets the alignment to 8 directly on the command line (via -a8) to match what the IDE does by default. The correct solution is probably to make alignment a feature in the toolset so that you can build a version of the Boost libraries using the same set of flags. For instance, you may be able to add to borland-tools.jam: flags borland CFLAGS <alignment>8 : -a8 ; flags borland CFLAGS <alignment>4 : -a4 ; Then remove the hardcoded "-a8" from the command line and build Boost like this: bjam -sTOOLS="borlandc" -sBUILD="<alignment>4" I hope that Jam-savvy Boosters will help correct any errors I made here :) Doug
Douglas Gregor wrote:
On Monday 03 March 2003 05:57 am, Russell Hind wrote:
Do (or should) all the bost headers force alignment before all structures/classes and then restore the alignment afterwards?
I don't see any reason that the Boost headers should do this unless they require a certain alignment to operate (and this should never be the case).
The problem goes deeper than the answer addresses. Certain compilers allow one to set the alignment ( and enumeration size, among other command-line changeable qualities which could affect the layout of data ) using #pragmas in the header files themselves. When this is done the compiler uses these settings consistently for the data in that header file no matter what other settings are used in a command-line or IDE build. Setting these very compiler-specific #pragmas protects the header file, and appropriate data it encompasses, from being passed incorrectly between the end-user and the implementation. This ability is a great boon to 3rd party developers of object-oriented software since it protects their users from data layout surprises. Both the Microsoft and Borland compilers support such #pragmas and use the conscientiously for all their RTL and other internal library header files. To say that Boost does not want to use the same technique for particular compilers, when it is available, appears very retrograde to me. Yes, it is possible that Boost may want to say that it doesn't know what the best alignment should be and wants to leave it to developers who build the libraries, but that will not protect the end user unless Boost makes it clear that developers may alter the distribution for themselves in order ot provide the correct alignments through these #pragmas. However, as a practical matter I see little benefit in this approach. The reasons for this is that alignment, enumeration size, and other possible issues relating to data layout are not issues which really need much serious decision. The various compilers do suggest the best default conditions in order to provide the maximum possible speed on various CPUs but in these days of faster CPUs, I personally wouldn't spend too much time worrying about setting other possible values. But whether one chooses to set the default values or other possible values in the appropriate header files through #pragmas, as long as one sets some reasonable value, the compiler will use it and avoid data mismatch. It is not good enough to just say, build your implementation from the command line using some value. This is because if it is not seen in the header file via the appropriate #pragma, when the end-user uses your OOP construct as defined in the header file, the end-user's command-line or IDE value at the time he compiles will be used, and this may not be the same as the value the implementor used to build. Nor is it good enough to use some command-line or IDE value when building your implementation and then telling the end-user that they have to use the exact same value when using your implementation. I hope I don't have to explain why this is so. I will anticipate two final objections to using particular compiler #pragmas in Boost implementation code: 1) It's not mandated in the C++ standard. Yes, #pragmas are implementation defined, but so what. Lots of other Boost code deals with implementation shortcomings in a compiler's adherence to the C++ standard and, while I hope for Boost someday to be able to chuck all those #ifdef and workarounds regarding many compiler's support for the C++ standard in the garbage, as soon as all C++ compilers are 100% conformant as they should theoretically be, surely a relatively benign use of #pragmas to eliminate data layout errors for end-users is worthwhile. 2) Boost developers have to know these #pragma tricks to use them. John Maddock already uses these #pragmas for VC++ and C++ Builder in his Boost.Regex++ library. Others will know them for these compilers, as well as other compilers if they exist, and will be glad to inform Boost developers about them for the compilers which they know about. Adding them to header files is a no-brainer experience for both VC++ and C++ Builder and may be for other compilers which have them. Finally, I admit as a 3rd party developer on Windows who has supplied implementation code for end-users of VC++ and C++ Builder, that I consider it almost "criminal" in a computer programming sense when an end-user is not protected by these #pragmas from possible changes he may make at the command-line or from within an IDE. Surely if Microsoft and Borland have gone out of the way top provide this fail-safe method of eliminating data layout errors, an intelligent implementor can use these methods.
At 07:09 PM 3/4/2003, Edward Diener wrote:
2) Boost developers have to know these #pragma tricks to use them.
I doubt you will make much head way trying to convince Boost developers to handcraft compiler specific #pragmas directly in their header files. Have you considered proposing a macro which will automatically apply the appropriate #pragma for the compiler? That way the knowledge of what #pragma to apply for each compiler only has to be maintained and tested in one place. --Beman
Beman Dawes wrote:
At 07:09 PM 3/4/2003, Edward Diener wrote:
2) Boost developers have to know these #pragma tricks to use them.
I doubt you will make much head way trying to convince Boost developers to handcraft compiler specific #pragmas directly in their header files.
Have you considered proposing a macro which will automatically apply the appropriate #pragma for the compiler? That way the knowledge of what #pragma to apply for each compiler only has to be maintained and tested in one place.
Excellent idea. Now why didn't I think of that <g>. It's the old forest and the trees thing, no doubt. The macro would have to be in the form of: BOOST_DATA_LAYOUT_BEGIN at the beginning of a header file surrounding any class/struct/union/enum declarations and BOOST_DATA_LAYOUT_END at the end. The ending macro is needed because many implementations of #pragma allow: #pragma push -someoptions and then eventually #pragma pop to automatically remove the options and set them to their previous value, which is what one wants to do in these header files. I imagine the header file which has these macros would be the compiler specific header files in the config.h hierarchy and that one would set such data layout options to their default values through #pragmas as the default expansion of the macro. Of course we could get fancier and introduce some macro parameters to control the most popular data layout options such as packing and enumeration size if desired, but I actually think we should keep it as simple as possible. Maybe BOOST_DATA_LAYOUT_BEGIN for the default values and BOOST_DATA_LAYOUT_BEGIN_VALUES with some macro parameters for the more complicated cases. I see there is a clever macro library as part of Boost but the documentation is so horrendous that I have just turned away from it in chagrin. Perhaps that macro library has some functionality to make these macros easier to specify and to work with. But I think you get the general gist.
On Tuesday 04 March 2003 10:16 pm, Edward Diener wrote:
Beman Dawes wrote:
Have you considered proposing a macro which will automatically apply the appropriate #pragma for the compiler? That way the knowledge of what #pragma to apply for each compiler only has to be maintained and tested in one place.
Excellent idea. Now why didn't I think of that <g>. It's the old forest and the trees thing, no doubt.
The macro would have to be in the form of:
BOOST_DATA_LAYOUT_BEGIN
at the beginning of a header file surrounding any class/struct/union/enum declarations and
BOOST_DATA_LAYOUT_END
at the end.
Would you willing to provide the definitions for these macros (or, as I suspect, begin/end headers)? I'd be happy to use them, but as I've never needed such a thing I don't know the particular pragmas to use. Doug
At 10:58 PM 3/4/2003, Douglas Gregor wrote:
On Tuesday 04 March 2003 10:16 pm, Edward Diener wrote:
Beman Dawes wrote:
Have you considered proposing a macro which will automatically apply the appropriate #pragma for the compiler? That way the knowledge of what #pragma to apply for each compiler only has to be maintained and tested in one place.
Excellent idea. Now why didn't I think of that <g>. It's the old forest
and the trees thing, no doubt.
The macro would have to be in the form of:
BOOST_DATA_LAYOUT_BEGIN
at the beginning of a header file surrounding any class/struct/union/enum declarations and
BOOST_DATA_LAYOUT_END
at the end.
Would you willing to provide the definitions for these macros (or, as I suspect, begin/end headers)? I'd be happy to use them, but as I've never needed such a thing I don't know the particular pragmas to use.
I'm in the same boat as Doug, and I expect other Boost developers are too. It isn't just a header (and docs) that are needed; test cases would be important too. It would be easy for mistakes in these macros to give the appearance of working, but actually do nothing. If I understand it, you can only tell they are working correctly with a fairly sophisticated build test that deliberately tries to use object files compiled with conflicting options. --Beman
Beman Dawes wrote:
At 10:58 PM 3/4/2003, Douglas Gregor wrote:
On Tuesday 04 March 2003 10:16 pm, Edward Diener wrote:
Beman Dawes wrote:
Have you considered proposing a macro which will automatically apply >> > the appropriate #pragma for the compiler? That way the knowledge of >> > what #pragma to apply for each compiler only has to be maintained and >> > tested in one place.
Excellent idea. Now why didn't I think of that <g>. It's the old forest
and the trees thing, no doubt.
The macro would have to be in the form of:
BOOST_DATA_LAYOUT_BEGIN
at the beginning of a header file surrounding any class/struct/union/enum declarations and
BOOST_DATA_LAYOUT_END
at the end.
Would you willing to provide the definitions for these macros (or, as I >suspect, begin/end headers)? I'd be happy to use them, but as I've never >needed such a thing I don't know the particular pragmas to use.
I'm in the same boat as Doug, and I expect other Boost developers are too.
It isn't just a header (and docs) that are needed; test cases would be important too. It would be easy for mistakes in these macros to give the appearance of working, but actually do nothing. If I understand it, you can only tell they are working correctly with a fairly sophisticated build test that deliberately tries to use object files compiled with conflicting options.
While I agree with test cases, at the simplest level of just setting the #pragmas to values, there should really be no problems. I am supposing that one can set a #pragma from within a #define, but if one can't, because a #define can't create another preprocessor statement, then the best generic choice, where one doesn't have to memorize the #pragma, is probably just creating a "begin" header file to be included at the beginning of appropriate headers with just the single starting pragma in it and a header file to be included at the end of the appropriate header with just a single ending pragma in it. Again John Maddock has used these #pragmas extensively in Regex++ to avoid data layout problems and I have used them in my libraries for the same reason, including my own components built on top of Regex++, and I have never encountered problems with them. In some of my classes I use different data layout options from Regex++ whose header files I include in my own and I have never had a problem reported about it. But I admit I have never tested both extensively by changing the data layout at the command-compiler/IDE compile level to find out although naturally I have tested my own implementation with default data layout options. But of course that doesn't make it fail-safe and it needs to be tested as you said. However, I would be very surprised if it didn't work as expected since I would expect to have heard screams and howls from Borland and MS users if it didn't.
Edward Diener wrote:
While I agree with test cases, at the simplest level of just setting the #pragmas to values, there should really be no problems. I am supposing that one can set a #pragma from within a #define, but if one can't, because a #define can't create another preprocessor statement,
It is implementation-defined whether or not the contents of a #pragma directive are macro expanded--I think that VC allows it. C99 explicitly allows it, but says that any #pragma that begins with STDC is explicitly _not_ macro expanded. C99, of course, has the _Pragma operator which can be generated by a macro expansion (not that that is relevent here). Paul Mensonides
Paul Mensonides wrote:
Edward Diener wrote:
While I agree with test cases, at the simplest level of just setting the #pragmas to values, there should really be no problems. I am supposing that one can set a #pragma from within a #define, but if one can't, because a #define can't create another preprocessor statement,
It is implementation-defined whether or not the contents of a #pragma directive are macro expanded--I think that VC allows it. C99 explicitly allows it, but says that any #pragma that begins with STDC is explicitly _not_ macro expanded. C99, of course, has the _Pragma operator which can be generated by a macro expansion (not that that is relevent here).
The opposite way was what I was wondering about. Can a #define create a #pragma which then is picked up as a preprocessor line ? As an example will this work: #define CREATE_PRAGMA #pragma somepragma // Code CREATE_PRAGMA // Code Will a compiler correctly pick up the #pragma as a preprocessor line or is the preprocessor stage finished once the macro is fully expanded ? I believe the latter is true, although I could be wrong. If I am right, then creating a Boost macro for these data layout #pragmas for BCB and VC++, and any other compiler which lets one fix data layout details such as packing from within each header file, will not work. In that case the alternative of a easily remembered header file name, which contains the appropriate #pragma, is a good alternative for adding such #pragmas in the correct place of header files which need such data layout reliability.
Edward Diener wrote:
It is implementation-defined whether or not the contents of a #pragma directive are macro expanded--I think that VC allows it. C99 explicitly allows it, but says that any #pragma that begins with STDC is explicitly _not_ macro expanded. C99, of course, has the _Pragma operator which can be generated by a macro expansion (not that that is relevent here).
The opposite way was what I was wondering about. Can a #define create a #pragma which then is picked up as a preprocessor line ? As an example will this work:
#define CREATE_PRAGMA #pragma somepragma
// Code CREATE_PRAGMA // Code
Will a compiler correctly pick up the #pragma as a preprocessor line or is the preprocessor stage finished once the macro is fully expanded ? I believe the latter is true, although I could be wrong.
It is not technically legal, but it might work anyway, as #pragmas usually aren't picked up by the preprocessor.
If I am right, then creating a Boost macro for these data layout #pragmas for BCB and VC++, and any other compiler which lets one fix data layout details such as packing from within each header file, will not work. In that case the alternative of a easily remembered header file name, which contains the appropriate #pragma, is a good alternative for adding such #pragmas in the correct place of header files which need such data layout reliability.
Well, #pragmas that the compiler doesn't understand are supposed to be ignored. However, using a header for it is also a good option. You can even use a macro to introduce the header if you like: #include CREATE_PRAGMA() Paul Mensonides
Paul Mensonides wrote:
Edward Diener wrote:
Will a compiler correctly pick up the #pragma as a preprocessor line or is the preprocessor stage finished once the macro is fully expanded ? I believe the latter is true, although I could be wrong.
It is not technically legal, but it might work anyway, as #pragmas usually aren't picked up by the preprocessor.
If I am right, then creating a Boost macro for these data layout #pragmas for BCB and VC++, and any other compiler which lets one fix data layout details such as packing from within each header file, will not work. In that case the alternative of a easily remembered header file name, which contains the appropriate #pragma, is a good alternative for adding such #pragmas in the correct place of header files which need such data layout reliability.
Well, #pragmas that the compiler doesn't understand are supposed to be ignored. However, using a header for it is also a good option. You can even use a macro to introduce the header if you like:
#include CREATE_PRAGMA()
Will the above really work ? I was always pretty sure that #includes have to be processed before macros are expanded and not after.
Edward Diener wrote:
Well, #pragmas that the compiler doesn't understand are supposed to be ignored. However, using a header for it is also a good option. You can even use a macro to introduce the header if you like:
#include CREATE_PRAGMA()
Will the above really work ? I was always pretty sure that #includes have to be processed before macros are expanded and not after.
Yes. Actually, it works on all compilers too. The file-iteration mechanism, among other things, of the pp-lib uses this behavior all the time. More specifically though, both the Python library and the MPL both use file-iteration extensively. Technically speaking, the #line, #include, #if, and #elif directives must be macro-expanded. For #error and #pragma directives, the behavior is unspecified, but the C99 standard explicitly says that #pragma's of the form: #pragma STDC xyz ...are _not_ macro expanded, even if other #pragma's are. All other directives make no sense to macro-expand. (#define, #undef, #else, #endif) Regards, Paul Mensonides
Edward Diener wrote: [...]
Again John Maddock has used these #pragmas extensively in Regex++ to avoid data layout problems and I have used them in my libraries for the same reason, including my own components built on top of Regex++, and I have never encountered problems with them.
The issue is less clear-cut than you make it seem. What we have here is a static library (Signals) that uses several header-only libraries (shared_ptr, Function, maybe others.) To "fix" the "alignment problem", we need not only #pragmify Signals, but those other header-only libraries as well. Furthermore, we need to be careful to not miss a header-only library that is used, directly or indirectly, by Signals, or any other static library. This impacts not only Signals users; it also affects those that only use header libraries. They don't need the "fix", and some of them may legitimately object to the binary compatibility settings that the headers have inflicted on them, especially if these settings lead to slower or larger code. The alternative is simple: always build libraries and applications using the _exact same_ settings. This is a good general advice, and it also applies to settings that we cannot "fix" using the #pragma method.
Peter Dimov wrote:
The alternative is simple: always build libraries and applications using the _exact same_ settings. This is a good general advice, and it also applies to settings that we cannot "fix" using the #pragma method.
I think this is limiting. I don't mind what setting the library uses, but I don't like the fact that my project options can cause crashes in the library. As an aside, if I want to build boost libraries forcing 4 byte alignment, how do I pass -a4 to bjam so that they are built the same? (And as asked elsewhere, how do I force BOOST_HAS_THREADS with bjam also?) Thanks Russell
Dear Boost group,
some how I get compiler erros while trying to BOOST_INSTALL_PROPERTY. My
test program is really tiny:
#ifndef DOMCLUST_VERTEX_PROPERTY
#define DOMCLUST_VERTEX_PROPERTY
#include
Russell Hind wrote:
As an aside, if I want to build boost libraries forcing 4 byte alignment, how do I pass -a4 to bjam so that they are built the same? (And as asked elsewhere, how do I force BOOST_HAS_THREADS with bjam also?)
Based on a cursory look at the Boost.Build documentation and the "borland" toolset file (borland-tools.jam), I think that the answers to these questions are bjam -sTOOLS=borland -sBUILD="<cxxflags>-a4" and bjam -sTOOLS=borland -sBUILD="<threading>multi" respectively. Alternatives include: - editing borland-tools.jam and changing -a8 to -a4. - editing borland-tools.jam and removing -a8, allowing your -a4 option in bcc32.cfg to take effect. - making a dedicated library project for Boost.Signals and building from the IDE, bypassing bjam. If this doesn't help, try the boost-install list: http://lists.boost.org/mailman/listinfo.cgi/boost-install
Peter Dimov wrote:
Based on a cursory look at the Boost.Build documentation and the "borland" toolset file (borland-tools.jam), I think that the answers to these questions are
bjam -sTOOLS=borland -sBUILD="<cxxflags>-a4"
and
bjam -sTOOLS=borland -sBUILD="<threading>multi"
Thanks Peter, that is what I was looking for.
If this doesn't help, try the boost-install list:
Any more queries and I'll post them here Cheers Russell
Peter Dimov wrote:
Edward Diener wrote: [...]
Again John Maddock has used these #pragmas extensively in Regex++ to avoid data layout problems and I have used them in my libraries for the same reason, including my own components built on top of Regex++, and I have never encountered problems with them.
The issue is less clear-cut than you make it seem.
What we have here is a static library (Signals) that uses several header-only libraries (shared_ptr, Function, maybe others.)
OK, I do see this problem.
To "fix" the "alignment problem", we need not only #pragmify Signals, but those other header-only libraries as well. Furthermore, we need to be careful to not miss a header-only library that is used, directly or indirectly, by Signals, or any other static library.
I view it this way. The people who create libraries, whether header-only or implementation, should be responsible for setting reasonable data layout details. After all, as I have previously mentioned, Borland sets data layout #pragmas for all of their RTL code even when the header is a class template, and therefore likely to be a header-only implementation.
This impacts not only Signals users; it also affects those that only use header libraries. They don't need the "fix", and some of them may legitimately object to the binary compatibility settings that the headers have inflicted on them, especially if these settings lead to slower or larger code.
Yes, I agree in theory. But compiler implementors do do this and I don't think they really get complaints saying "Gee, I don't like your pack alignment for your XXX class. It's really slowing me down."
The alternative is simple: always build libraries and applications using the _exact same_ settings. This is a good general advice, and it also applies to settings that we cannot "fix" using the #pragma method.
I don't think the alternative is simple. Do you feel good forcing end-users of Boost to build their applications according to what settings you specify ? And what happens if another 3rd party developer tells their end-users that they must build their applications to settings they specify and it is not the same as the Boost settings ? And what if the end-user needs to change from the Boost settings for their own purposes ? Dictating to the end-user what you insist his settings must be in order to use libraries effectively is not my idea of a simple or good alternative. I recognize that you have brought up valid points, but I would still much rather protect the end-user against inadvertent data layout problems if they change their own global settings than worry that they might not like the data layout I set for my own classes.
Douglas Gregor wrote:
On Tuesday 04 March 2003 10:16 pm, Edward Diener wrote:
Beman Dawes wrote:
Have you considered proposing a macro which will automatically apply the appropriate #pragma for the compiler? That way the knowledge of what #pragma to apply for each compiler only has to be maintained and tested in one place.
Excellent idea. Now why didn't I think of that <g>. It's the old forest and the trees thing, no doubt.
The macro would have to be in the form of:
BOOST_DATA_LAYOUT_BEGIN
at the beginning of a header file surrounding any class/struct/union/enum declarations and
BOOST_DATA_LAYOUT_END
at the end.
Would you willing to provide the definitions for these macros (or, as I suspect, begin/end headers)? I'd be happy to use them, but as I've never needed such a thing I don't know the particular pragmas to use.
I can give anyone the #pragmas for VC++ and BCB and their meanings for data layout. You, or any other Boost developer, should be able to take it from there. John Maddock also knows them well since there are in the Regex++ header files. For other compilers, if they exist, others would have to supply them. ---------------------------------------------------------------------------- ---------------------------------------------------- For BCB the begin and end #pragmas would be of the form: #pragma option push -option [ -option ... ] #pragma option pop where option for data layout would be: -an = packing, where n = 1,2,4,8,16 with the default being 8 -b(-) = enum size, where -b = integer size ( default ) and -b- = byte-sized when possible -Ve(-) = zero-length empty base classes where -Ve = turns it on and -Ve- = turns it off ( default ) -Vx(-) = zero-length class data members where -Vx = turns it on and -Vx- = turns it off ( default ) A setting for a header which sets the defaults would be #pragma option push -a8 -b -Ve- -Vx- // Class/struct/union/enums #pragma option pop ---------------------------------------------------------------------------- ---------------------------------------------------- For VC++ the begin and end #pragmas just encompass the packing alignment since VC++ doesn't allow any other data layout alternatives as BCB does above. The form is #pragma pack(push,n) #pragma pack(pop) where n is your 1,2,4,8,16 packing with 8 being the default. A setting for a header which sets the default would be #pragma pack(push,8) // Class/struct/unions #pragma pack(pop) ---------------------------------------------------------------------------- ----------------------------------------------------- Two important things to realize when using these in header files 1) Don't have any intervening #includes in between the pushing and popping of options 2) You can do multiple and nested push and pops so there is much flexibility with this system, but of course KISS still applies very well here.
Edward Diener wrote:
#pragma push -someoptions
The options from windows.h of C++Builder 6 Pro are #pragma option push -b -a8 -pc -A- /*P_O_Push*/ along with the pop at the bottom. These are: -b: Force enums to be of integer size -a8: Force 8 byte alignment on structs -pc: Force 'C' calling convention -A-: Disable use ANSI keywords and extensions (because windows headers won't compile in strict ansi mode, apparently) For Borland, it might also be worth adding -Vg- which disables CodeGuard. Just in case there are allocations done in inline code in header files which are then freed in methods in the compiled lib (which may/may not have been built with CodeGuard). Also, being able to disable some of these options or all of them with a #define would also be useful so that you could link with the code directly (as I have done to get round the current problems) and there fore build with CodeGuard and other options to test the library. Unfortunately I haven't used any compilers other than bcc32 (for a long time anyway) to be able to help/test other versions of the headers, but I can help with the Borland version of them. Cheers Russell
Russell Hind wrote:
For Borland, it might also be worth adding -Vg- which disables CodeGuard. Just in case there are allocations done in inline code in header files which are then freed in methods in the compiled lib (which may/may not have been built with CodeGuard).
Disabling CodeGuard in this way doesn't work as the CodeGuard code is only generated at the point the inline function is actually inlined (i.e. where our code calls it) so wrapping the header in -vG- doesn't disable CodeGuard for the code in it. Russell
Edward Diener wrote: [...]
Finally, I admit as a 3rd party developer on Windows who has supplied implementation code for end-users of VC++ and C++ Builder, that I consider it almost "criminal" in a computer programming sense when an end-user is not protected by these #pragmas from possible changes he may make at the command-line or from within an IDE. Surely if Microsoft and Borland have gone out of the way top provide this fail-safe method of eliminating data layout errors, an intelligent implementor can use these methods.
It is certainly "criminal" to not use the appropriate #pragma mechanism if you provide a binary compiler-specific distribution that depends on certain alignment (and other options affecting binary compatibility: enum size, empty base/member optimization, and so on.)
Russell Hind wrote:
I have built the boost::signals library with C++Builder 6 Pro Update 4 and am running into problems:
[...]
b) If I do use quad word alignment, then the object constructs correctly, but when I connect a method to it with
void VoidFunc(void) { }
int main(int argc, char* argv[]) { boost::signal0<void> s; s.connect(&VoidFunc); }
the program hangs. Turning on CodeGuard shows a similar problem to that above. The object was allocated with a size of 12 bytes, but code is trying to access byte 16 in the object (I guess this is a similar alignment problem). The callstack is
0041E44E boost::counted_base::dispose(this=:00C04360)
counted_base::dispose() is an empty function, so this looks like a CodeGuard false alarm. One possible reason for the real problem is runtime library mismatch between the signals library and your executable. counted_base contains a mutex in multithreaded builds.
Do (or should) all the bost headers force alignment before all structures/classes and then restore the alignment afterwards?
No. The compiler options used to build the application and the libraries it depends on must match. The headers cannot magically fix the (general) problem for you; even if we focus on one particular compiler/platform - and we shouldn't - some of the options are global.
Currently, I have to link directly with the signals source code to get use the library.
This is what I'd do, too. The other alternative is to build several .lib files that match the options specified in your various project configurations (Debug, Debug MT, Release, Release MT, or however their canonical names are in BCB).
Peter Dimov wrote:
Currently, I have to link directly with the signals source code to get use the library.
This is what I'd do, too. The other alternative is to build several .lib files that match the options specified in your various project configurations (Debug, Debug MT, Release, Release MT, or however their canonical names are in BCB).
The problem with linking with the source directly (not a major problem) is that we have our own Thread.cpp which we're planning on turning into a wrapper around boost::thread (it currently uses Win32 threads directly). Unfortunately C++Builder won't allow 2 cpp files in the same project with the same name, even if they reside in different directories. We can get around this re-naming either the boost thread.cpp or own own, but it is a bit of a pain (but we haven't run into a problem with the thread library wrt this). As mentioned in the rest of the thread by Edward Diener, bcc32 supports #pragma option push and #pragma option pop to temporarily force compiler options, which as also mentioned, is how the headers that come with the compiler are configured so that the alignment for anything declared in there headers matches what was built into the .lib and therefore we can use our own compiler options for our code but not run into any problems with the pre-compiled libraries. Do you not think the same approach would work in boost? (I don't know how much support there is for push and pop of options in other compilers, though) Cheers Russell
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
Russell Hind wrote:
As mentioned in the rest of the thread by Edward Diener, bcc32 supports #pragma option push and #pragma option pop to temporarily force compiler options, which as also mentioned, is how the headers that come with the compiler are configured so that the alignment for anything declared in there headers matches what was built into the .lib and therefore we can use our own compiler options for our code but not run into any problems with the pre-compiled libraries.
Do you not think the same approach would work in boost? (I don't know how much support there is for push and pop of options in other compilers, though)
Microsoft has #pragma pack(push,n) #pragma pack(pop) for packing and since all enum sizes are the same in VC++, that more or less takes care of their data layout problems. I wouldn't be surprised if other compilers also have appropriate #pragmas also, but VC++ and BCB are the only ones in C++ I am currently using. Maybe a gcc expert knows something about its technique, if any, to ensure data layout compatibility within the header file itself.
Someone that knows the C/C++ Spec better than should confirm or deny this, but somewhere in the deep dark recesses of my memory there is something about pragma's and macros not working together. That is pragma's cannot appear in macros and expect to be acted upon. Can anyone confirm or deny this from the spec (different compilers may or may not support this "feature"). ...Duane
Peter Dimov wrote:
the program hangs. Turning on CodeGuard shows a similar problem to that above. The object was allocated with a size of 12 bytes, but code is trying to access byte 16 in the object (I guess this is a similar alignment problem). The callstack is
0041E44E boost::counted_base::dispose(this=:00C04360)
counted_base::dispose() is an empty function, so this looks like a CodeGuard false alarm.
One possible reason for the real problem is runtime library mismatch between the signals library and your executable. counted_base contains a mutex in multithreaded builds.
You may well be correct here. Stepping through the code with the debug version of the built library, shows that in slot.cpp line 44 scoped_connection safe_connection(watch_bound_objects); This creates a shared_count. The shared_count doesn't create a mutex object (so I assume the library is being built without BOOST_HAS_THREADS. When releasing the safe_connection, releasing the shared_count shows it to have a mutex (I guess because my program has multi-threading enabled. Question is: How do I force BOOST_HAS_THREADS with bjam to build the library with multi-threading? I currently build the libraries using bjam -sTOOLS=borland Hope someone can help with this? Thanks Russell
participants (8)
-
Beman Dawes
-
Douglas Gregor
-
Duane Murphy
-
Edward Diener
-
Martin Okrslar
-
Paul Mensonides
-
Peter Dimov
-
Russell Hind