By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,600 Members | 1,683 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,600 IT Pros & Developers. It's quick & easy.

STL objects and binary compatibility

P: n/a
Hi,

What does it mean for an object to be binary compatible? And why
aren't STL objects binary compatible? Any insights, links, resources
for further reading are greatly appreciated.

Thanks.
Jun 27 '08 #1
Share this Question
Share on Google+
17 Replies


P: n/a
os******@gmail.com wrote:
Hi,

What does it mean for an object to be binary compatible? And why
aren't STL objects binary compatible? Any insights, links, resources
for further reading are greatly appreciated.
It sounds like you're a little confused.

Binary compatablity usually is associated with a context.

If you build with different versions of the STL or with various options
that render binary incompatibility, then this is your choice.

Please elaborate what you're really concerned about.
Jun 27 '08 #2

P: n/a
On May 6, 7:56 am, Gianni Mariani <gi4nos...@mariani.wswrote:
osama...@gmail.com wrote:
What does it mean for an object to be binary compatible? And why
aren't STL objects binary compatible? Any insights, links, resources
for further reading are greatly appreciated.
It sounds like you're a little confused.
Between C++ objects and object files? Whether two object files
are binary compatible makes sense as a question.
Binary compatablity usually is associated with a context.
It is usually associated with compiler output: object files and
libraries. If two files are object compatible, they can be
linked together and will work as expected. (I know you know
that, but I think it's the answer to the question the original
poster tried to ask.)
If you build with different versions of the STL or with
various options that render binary incompatibility, then this
is your choice.
If you're using third party libraries, you don't always have a
choice. You have to compile with whatever options are necessary
to ensure binary compatibility with what they furnish. (For
starters, this usually means compiling with CC, and not g++.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #3

P: n/a
further reading are greatly appreciated.
>
It sounds like you're a little confused.

Binary compatablity usually is associated with a context.

If you build with different versions of the STL or with various options
that render binary incompatibility, then this is your choice.

Please elaborate what you're really concerned about.
Sorry my question was not very clear. In other words, can STL Objects
cross DLL boundaries. For example. Can we pass STL objects between
different binaries by reference safely?
Jun 27 '08 #4

P: n/a
os******@gmail.com wrote:
further reading are greatly appreciated.
>It sounds like you're a little confused.

Binary compatablity usually is associated with a context.

If you build with different versions of the STL or with various options
that render binary incompatibility, then this is your choice.

Please elaborate what you're really concerned about.

Sorry my question was not very clear. In other words, can STL Objects
cross DLL boundaries. For example. Can we pass STL objects between
different binaries by reference safely?
Only if you're using the same STL library (or binary compatible
library). This usually means you're stuck with making sure that the DLL
versions are using the same compiler major revision.
Jun 27 '08 #5

P: n/a
os******@gmail.com wrote:
further reading are greatly appreciated.
>It sounds like you're a little confused.

Binary compatablity usually is associated with a context.

If you build with different versions of the STL or with various options
that render binary incompatibility, then this is your choice.

Please elaborate what you're really concerned about.

Sorry my question was not very clear. In other words, can STL Objects
cross DLL boundaries. For example. Can we pass STL objects between
different binaries by reference safely?
That question goes beyond C++, you'd better ask it on a windows group.

--
Ian Collins.
Jun 27 '08 #6

P: n/a
On May 6, 9:10 pm, Gianni Mariani <gi4nos...@mariani.wswrote:
osama...@gmail.com wrote:
further reading are greatly appreciated.
It sounds like you're a little confused.
Binary compatablity usually is associated with a context.
If you build with different versions of the STL or with
various options that render binary incompatibility, then
this is your choice.
Please elaborate what you're really concerned about.
Sorry my question was not very clear. In other words, can
STL Objects cross DLL boundaries. For example. Can we pass
STL objects between different binaries by reference safely?
Only if you're using the same STL library (or binary
compatible library). This usually means you're stuck with
making sure that the DLL versions are using the same compiler
major revision.
And the same compiler options. At least some of them can also
affect the binary compatibility. Using g++, try linking code
compiled with -D_GLIBCXX_DEBUG, and code compiled without it.
(Actually, it links just fine---it just crashes at runtime.)
And while I've not actually tried it, I would expect similar
problems with VC++ using mixtures of /Gd, /Gr and /Gz or
different values of /vm<xor /Zc:wchar_t. (In practice,
without /vmg, you'll get binary incompatibility anyway.)

Note too (to the original poster) that whether you're using
dynamic linking or not is really irrelevant. If the object or
library files are not binary compatible, you can't statically
link them either (or the results of the static link will crash).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #7

P: n/a
os******@gmail.com wrote in news:06aeb05a-483c-4503-b190-
81**********@u6g2000prc.googlegroups.com:
further reading are greatly appreciated.
>>
It sounds like you're a little confused.

Binary compatablity usually is associated with a context.

If you build with different versions of the STL or with various options
that render binary incompatibility, then this is your choice.

Please elaborate what you're really concerned about.

Sorry my question was not very clear. In other words, can STL Objects
cross DLL boundaries. For example. Can we pass STL objects between
different binaries by reference safely?
Yes, no, maybe. Since you use the term DLL, I will assume that you are
talking windows. The problems you can have under windows have to do with
memory allocation. If you pass a collection to a dll and it adds an object
to it and if that addition causes the collection to allocate memory, then
since it is using code compiled into the dll, it will allocate memory from
the dll's heap and return it to the main program. This can cause problems
with memory accounting when the collection is later freed. Especially if
the dll is unloaded before the collection is destroyed. This effect can be
reduced if you use the DLL version of the crt for all dlls and the exe.
This is because the memory for everything then comes from the crt dll
rather than the individual dll/exe. Along those same lines, if you plan on
unloading your dlls make very sure that every object allocated from that
dll has been destroyed first or you will get a fault when you eventually do
get around to destroying those objects. Something about the destructors
not being loaded into memory any more makes the system get upset. :)

HTH,
joe
Jun 27 '08 #8

P: n/a
Thank you all for responding. Your input helped clear things a lot.
Along those same lines, if you plan on
unloading your dlls make very sure that every object allocated from that
dll has been destroyed first or you will get a fault when you eventually do
get around to destroying those objects. Something about the destructors
not being loaded into memory any more makes the system get upset. :)
This excerpt from Effective C++, Iterm 18 adds to what you said:

"An especially nice feature of tr1::shared_ptr is that it
automatically uses its per-pointer deleter to eliminate another
potential client error, the "cross-DLL problem." This problem crops
up when an object is created using new in one dynamically linked
library (DLL) but is deleted in a different DLL. On many platforms,
such cross-DLL new/delete pairs lead to runtime errors.
tr1:;shared_ptr avoids the problem, because its default deleter uses
delete from the same DLL where the tr1::shared_ptr is created."
Jun 27 '08 #9

P: n/a
os******@gmail.com wrote in
news:74**********************************@a9g2000p rl.googlegroups.com:
Thank you all for responding. Your input helped clear things a lot.
>Along those same lines, if you plan on
unloading your dlls make very sure that every object allocated from
that dll has been destroyed first or you will get a fault when you
eventually do get around to destroying those objects. Something
about the destructors not being loaded into memory any more makes the
system get upset. :)

This excerpt from Effective C++, Iterm 18 adds to what you said:

"An especially nice feature of tr1::shared_ptr is that it
automatically uses its per-pointer deleter to eliminate another
potential client error, the "cross-DLL problem." This problem crops
up when an object is created using new in one dynamically linked
library (DLL) but is deleted in a different DLL. On many platforms,
such cross-DLL new/delete pairs lead to runtime errors.
tr1:;shared_ptr avoids the problem, because its default deleter uses
delete from the same DLL where the tr1::shared_ptr is created."
And that is true. The problem with STL collections is that they can sneak
an allocation in on you for one of their internal structures and the
current versions don't take any steps to guarantee that the internal
structure gets deleted where it was allocated. AFAIK, this is a problem
only for classes where the implementation is all in the header, allowing
for the inlining of methods that may allocate memory.

joe
Jun 27 '08 #10

P: n/a
James Kanze <ja*********@gmail.comwrote in news:acd6384e-e719-4324-
9d***************@i76g2000hsf.googlegroups.com:
On May 6, 9:10 pm, Gianni Mariani <gi4nos...@mariani.wswrote:
>osama...@gmail.com wrote:
[...]
Sorry my question was not very clear. In other words, can
STL Objects cross DLL boundaries. For example. Can we pass
STL objects between different binaries by reference safely?
>Only if you're using the same STL library (or binary
compatible library). This usually means you're stuck with
making sure that the DLL versions are using the same compiler
major revision.

And the same compiler options. At least some of them can also
affect the binary compatibility. Using g++, try linking code
compiled with -D_GLIBCXX_DEBUG, and code compiled without it.
(Actually, it links just fine---it just crashes at runtime.)
And while I've not actually tried it, I would expect similar
problems with VC++ using mixtures of /Gd, /Gr and /Gz or
different values of /vm<xor /Zc:wchar_t. (In practice,
without /vmg, you'll get binary incompatibility anyway.)
The current annoyance in VC++ is the _SECURE_SCL thing; it is on by
default in both Debug and Release builds. IMHO it should be switched off
in optimized builds (what would be the point of optimization otherwise?).
There was a recent thread in this NG about C++ and Java speed wars where
C++ honour could only be saved by turning _SECURE_SCL off...

However, if some DLL-s happen to be compiled with different settings and
are trying to expose or exchange STL containers or iterators, the program
will crash at run-time with mysterious error messages.

Note that this is a preprocessor definition which can reside in an header
file as well, so even ensuring the same compiler options does not
guarantee binary compatibility. In a quality implementation binarily
incompatible object files should not link, but it seems this is not the
case in practice.

Paavo

Jun 27 '08 #11

P: n/a
On May 8, 11:08 pm, Paavo Helde <nob...@ebi.eewrote:
James Kanze <james.ka...@gmail.comwrote in news:acd6384e-e719-4324-
9dca-7a482ec36...@i76g2000hsf.googlegroups.com:
On May 6, 9:10 pm, Gianni Mariani <gi4nos...@mariani.wswrote:
osama...@gmail.com wrote:
[...]
Sorry my question was not very clear. In other words, can
STL Objects cross DLL boundaries. For example. Can we pass
STL objects between different binaries by reference safely?
Only if you're using the same STL library (or binary
compatible library). This usually means you're stuck with
making sure that the DLL versions are using the same compiler
major revision.
And the same compiler options. At least some of them can also
affect the binary compatibility. Using g++, try linking code
compiled with -D_GLIBCXX_DEBUG, and code compiled without it.
(Actually, it links just fine---it just crashes at runtime.)
And while I've not actually tried it, I would expect similar
problems with VC++ using mixtures of /Gd, /Gr and /Gz or
different values of /vm<xor /Zc:wchar_t. (In practice,
without /vmg, you'll get binary incompatibility anyway.)
The current annoyance in VC++ is the _SECURE_SCL thing; it is
on by default in both Debug and Release builds.
I don't think so. You define whether it is on or off when you
invoke the compiler; you can turn it off in debug builds, and
leave it on in release builds, if that's what you want.
Typically, of course, you'll want it on in both. Typically, of
course, you'll want exactly the same compiler options in your
debug builds as in your release builds, so that your unit tests
test the code that is actually delivered.
IMHO it should be switched off in optimized builds (what
would be the point of optimization otherwise?).
Well, obviously, if the profiler shows you have performance
problems due to the extra checks, then you'll have to turn it
off. I'm not familiar enough with VC++ to be sure, but I rather
suspect that you have to compile everything with the same value
for it; in other words, that it affects binary compatibility.
There was a recent thread in this NG about C++ and Java speed
wars where C++ honour could only be saved by turning
_SECURE_SCL off...
There are a couple of recent threads in this NG that are full of
nonsense. Who cares?
However, if some DLL-s happen to be compiled with different
settings and are trying to expose or exchange STL containers
or iterators, the program will crash at run-time with
mysterious error messages.
In other words, it affects binary compatibility.

From what I've been led to believe, if you use the default
settings for release and debug builds in Visual Studios, you
don't have binary compatibility between the two. I'll admit
that I only have hearsay for that, however, since I've yet to
find a compiler where the default settings were usable for
anything serious, VC++ included. I systematically set things as
I need them.
Note that this is a preprocessor definition which can reside
in an header file as well, so even ensuring the same compiler
options does not guarantee binary compatibility. In a quality
implementation binarily incompatible object files should not
link, but it seems this is not the case in practice.
Yes. This is exactly the problem I was talking about with g++.
And you've got a good point about something being defined (or
undef'ed) in a header: _GLIBCXX_DEBUG is also, formally, a
macro.

Of course, both _GLIBCXX_DEBUG and _SECURE_SCL are squarely in
the implementation namespace. Any code which does anything with
them is invoking undefined behavior. So the answer to that is:
don't do it (and don't use any third party code which is so
poorly written as to do it).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #12

P: n/a
On 13 Mai, 01:35, Paavo Helde <nob...@ebi.eewrote:
Maybe I should have been more precise. The alarms are not "false" in the
sense that the code has UB by the standard. On the other hand, the code
appears to have defined meaning and guaranteed behavior by the same
implementation which raises the alarms. Example 1:

#include <vector>
#include <iostream>
#include <ostream>

double summate(const double* from, const double* to) {
* * * * double sum=0.0;
* * * * for(const double* p=from; p!=to; ++p) {
* * * * * * * * sum += *p;
* * * * }
* * * * return sum;

}

int main() {
* * * * std::vector<doublev;
* * * * v.push_back(3.1415926);
* * * * v.push_back(2.7182818);
* * * * size_t n=v.size();
* * * * std::cout << summate(&v[0], &v[n]) << "\n";

}

In real life, summate() is some legacy function accepting double*
pointers, which has to be interfaced with a new std::vector array used
for better memory management. The expression &v[n] is formally UB. VC++
on XP crashes the application with the message "test.exe has encountered
a problem and needs to close. *We are sorry for the inconvenience.". If
_SECURE_SCL is defined to 0, the program runs nicely and produces the
expected results.
I think the problem is not only formal in this case, because the
expression v[n], or v.operator[](n) dereferences an invalid pointer.
Okay, the program may happen to work, but the checked iterator alarm/
crash is justified by the fact that it exposes a potential problem
that could easily be avoided by using (&v[0] + n) instead of &v[n].

--
DP
Jun 27 '08 #13

P: n/a
Triple-DES <De**********@gmail.comwrote in
news:0d**********************************@k37g2000 hsf.googlegroups.com:
On 13 Mai, 01:35, Paavo Helde <nob...@ebi.eewrote:
>Maybe I should have been more precise. The alarms are not "false" in
the sense that the code has UB by the standard. On the other hand,
the code appears to have defined meaning and guaranteed behavior by
the same implementation which raises the alarms. Example 1:

#include <vector>
#include <iostream>
#include <ostream>

double summate(const double* from, const double* to) {
* * * * double sum=0.0;
* * * * for(const double* p=from; p!=to; ++p) {
* * * * * * * * sum += *p;
* * * * }
* * * * return sum;

}

int main() {
* * * * std::vector<doublev;
* * * * v.push_back(3.1415926);
* * * * v.push_back(2.7182818);
* * * * size_t n=v.size();
* * * * std::cout << summate(&v[0], &v[n]) << "\n";

}

In real life, summate() is some legacy function accepting double*
pointers, which has to be interfaced with a new std::vector array
used for better memory management. The expression &v[n] is formally
UB. VC++ on XP crashes the application with the message "test.exe has
encountered a problem and needs to close. *We are sorry for the
inconvenience.". If _SECURE_SCL is defined to 0, the program runs
nicely and produces the expected results.

I think the problem is not only formal in this case, because the
expression v[n], or v.operator[](n) dereferences an invalid pointer.
Okay, the program may happen to work, but the checked iterator alarm/
crash is justified by the fact that it exposes a potential problem
that could easily be avoided by using (&v[0] + n) instead of &v[n].
Yes, that's why I added another example where it could not be avoided
*so* easily. Also here, &v[0] fails for an empty vector.

These are actual examples from a former coworker code, which stopped
working in a new compiler version. I have fixed all locations I have
found of course. I'm worried about locations which I might have not
found.

Regards
Paavo
Jun 27 '08 #14

P: n/a

----- Original Message -----
From: "Paavo Helde" <no****@ebi.ee>
Newsgroups: comp.lang.c++
Sent: Tuesday, May 13, 2008 6:27 PM
Subject: Re: STL objects and binary compatibility

<...>

Now I have to deliver the final application (Release mode) to the
customer. The question is whether to keep the checked iterators feature
on or not. I have the following choices:

a) Keep the checked iterators on: this makes the program somewhat slower,
and if a corner case of this UB is encountered, the probability of a
customer support problem appearing is 100%.

b) Switch them off: the code is faster, and if this corner case of UB is
encountered, the probability to have a customer support problem is below
100%
Its obvious what you *should* do...

:-)

regards
Andy Little
Jun 27 '08 #15

P: n/a
On May 7, 12:08 pm, James Kanze <james.ka...@gmail.comwrote:
On May 6, 9:10 pm, Gianni Mariani <gi4nos...@mariani.wswrote:
osama...@gmail.com wrote:
further reading are greatly appreciated.
>It sounds like you're a little confused.
>Binary compatablity usually is associated with a context.
>If you build with different versions of the STL or with
>various options that render binary incompatibility, then
>this is your choice.
>Please elaborate what you're really concerned about.
Sorry my question was not very clear. In other words, can
STL Objects cross DLL boundaries. For example. Can we pass
STL objects between different binaries by reference safely?
Only if you're using the same STL library (or binary
compatible library). This usually means you're stuck with
making sure that the DLL versions are using the same compiler
major revision.

And the same compiler options. At least some of them can also
affect the binary compatibility. Using g++, try linking code
compiled with -D_GLIBCXX_DEBUG, and code compiled without it.
(Actually, it links just fine---it just crashes at runtime.)
And while I've not actually tried it, I would expect similar
problems with VC++ using mixtures of /Gd, /Gr and /Gz or
different values of /vm<xor /Zc:wchar_t. (In practice,
without /vmg, you'll get binary incompatibility anyway.)
How does this affect exceptions? If I read correctly,
does it mean that it is a bad idea to throw exceptions from
a library function because the library might be compiled
with different compile options than the application using
the library?
Jun 27 '08 #16

P: n/a
ajalkane wrote:
On May 7, 12:08 pm, James Kanze <james.ka...@gmail.comwrote:
>And the same compiler options. At least some of them can also
affect the binary compatibility. Using g++, try linking code
compiled with -D_GLIBCXX_DEBUG, and code compiled without it.
(Actually, it links just fine---it just crashes at runtime.)
And while I've not actually tried it, I would expect similar
problems with VC++ using mixtures of /Gd, /Gr and /Gz or
different values of /vm<xor /Zc:wchar_t. (In practice,
without /vmg, you'll get binary incompatibility anyway.)

How does this affect exceptions? If I read correctly,
does it mean that it is a bad idea to throw exceptions from
a library function because the library might be compiled
with different compile options than the application using
the library?
Typically this isn't a problem. Consider your environment's run time
library, it will throw exceptions as specified by the standard.

--
Ian Collins.
Jun 27 '08 #17

P: n/a
On May 14, 7:34 am, Ian Collins <ian-n...@hotmail.comwrote:
ajalkane wrote:
On May 7, 12:08 pm, James Kanze <james.ka...@gmail.comwrote:
And the same compiler options. At least some of them can also
affect the binary compatibility. Using g++, try linking code
compiled with -D_GLIBCXX_DEBUG, and code compiled without it.
(Actually, it links just fine---it just crashes at runtime.)
And while I've not actually tried it, I would expect similar
problems with VC++ using mixtures of /Gd, /Gr and /Gz or
different values of /vm<xor /Zc:wchar_t. (In practice,
without /vmg, you'll get binary incompatibility anyway.)
How does this affect exceptions? If I read correctly, does
it mean that it is a bad idea to throw exceptions from a
library function because the library might be compiled with
different compile options than the application using the
library?
Typically this isn't a problem. Consider your environment's
run time library, it will throw exceptions as specified by the
standard.
It depends. It may also throw exceptions in case of undefined
behavior. And binary compatibility will affect any exceptions
you throw as well.

And I really should have mentionned the /EH options as well. If
you compile some code without them, you may have binary
compatibility problems if other code is compiled with one of
them. I tend to forget them, however, since if you use the
default (no /EH options, e.g. no exception support), you get
compiler errors as soon as you include any of the standard
headers (which do use exceptions); in practice, /EHs is about
the only thing that makes sense (sort of like /vmg---I don't
even understand why the option is there, much less why the
default is not to use the only reasonable value for it).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #18

This discussion thread is closed

Replies have been disabled for this discussion.