Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

DLLs and the Standard Template Library

8 views
Skip to first unread message

Michael Winter

unread,
Sep 17, 2003, 12:26:40 PM9/17/03
to
Apologies for the off-topic post. I can't contact the Microsoft Visual C++
groups.

In a post to comp.lang.c++ (Standard Template Library as container for
Objects - original post and reply at the end), I asked why an error occurred
when a vector that contained classes that contained vectors that contained
(you get the picture) dropped out of scope and was removed from the stack.
Specifically, an assertion within the CRT new/delete routines occurred in
debug mode and access violations in release mode.
In one of the replies, I was told that there is an issue with certain
combinations of the run-time libraries (static/dll, single-/multi-threaded).
Can anyone elaborate what precisely these issues are and how to avoid them?

Thanks in advance,
Mike

--
Michael Winter
M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply)


-----------------------------
Original post:

Is the Standard Template Library capable of storing complete objects rather
than pointers. For example, would either of the vectors below (a, c)
function correctly (note the member in C).

class A {};
class B {};
class C {
stl::vector<B> b;
};

std::vector<A> a;
std::vector<C> c;

The reason that I ask is that I had something similar to this in a library
that I was writing. It worked as far as I could add objects to the various
containers and index through them. However, when the objects dropped out of
scope and deallocated their lists an assertion was thrown (I forget the
message, but it was from deep within the bowels of CRT new) for each class
object that had a vector containing a class. In release mode, all hell
broke loose (access violations, everywhere).
I know that this would seem to scream, "No, don't use STL containers with
objects!" but I was wondering if there was any other explanation, like using
STL with DLLs, or linking the wrong run-time and using STL, or using
different and incompatible run-times between the test program and the DLL
project. So, could those be the cause, or is it just a case of using
pointers to objects instead? Would that include the stl::auto_ptr template
class?
Are there any rules that should be followed when it comes to the various
run-time libraries? Such as what combinations produce problems, and when
generally should the different libraries be used? Those sorts of details
seemed to be omitted from books, so are there any good references out there
(preferably web-sites, I'm poor, but *really* excellent books are OK).

Thank you (in advance),

Mike

--
Michael Winter
M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply by e-mail)


----------------------------
First reply:

It was most probably using DLLs. There is some issue (off-topic here) on
Windows if you static-link the runtime to the DLL and the EXE you will get
separate heaps and trouble.

The STL containers are fully capable of storing complete objects and
destroying them properly when they are removed.

--
Attila aka WW


-------------------------
Second reply:

Basically, storing objects in std:: containers is safe as long as the class
of those objects
support value semantics. Your object will basically need a safe (and
preferably efficient)
default constructor, copy constructor and assignment operator. I suspect
that in the example
you show below you are using a class that does not (properly) implement
these, and that
is what causes the problem at cleanup (double deletes maybe?).

Marijn Haverbeke

David Lowndes

unread,
Sep 17, 2003, 12:37:40 PM9/17/03
to
>In one of the replies, I was told that there is an issue with certain
>combinations of the run-time libraries (static/dll, single-/multi-threaded).
>Can anyone elaborate what precisely these issues are and how to avoid them?

Mike,

The issue is usually that you've got an EXE built with one form of the
library, and a DLL with another, and you're passing heap allocated
objects across the DLL/EXE boundary. Since the different components
are using different heaps, you hit big problems. The solution is to
ensure that if you pass heap allocated objects between the DLL/EXE
that all the components use the same common heap - i.e. you must use
the DLL version of the run-time library. Similarly, you can't mix
debug & release components, because they too have different heap
memory managers.

HTH
Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq

Michael Winter

unread,
Sep 17, 2003, 2:16:06 PM9/17/03
to
> The issue is usually that you've got an EXE built with one form of the
> library, and a DLL with another, and you're passing heap allocated
> objects across the DLL/EXE boundary. Since the different components
> are using different heaps, you hit big problems. The solution is to
> ensure that if you pass heap allocated objects between the DLL/EXE
> that all the components use the same common heap - i.e. you must use
> the DLL version of the run-time library.

What then, out of interest, would be the best strategy for releasing DLLs?
What if, for example, a DLL uses threads but an .exe that uses the DLL
doesn't, or vice versa. Should one create both multi- and single-threaded
versions and then use them as appropriate?

> Similarly, you can't mix
> debug & release components, because they too have different heap
> memory managers.

Didn't think about that (slaps head).

> HTH

It did :)

David Lowndes

unread,
Sep 17, 2003, 2:51:00 PM9/17/03
to
>What then, out of interest, would be the best strategy for releasing DLLs?
>What if, for example, a DLL uses threads but an .exe that uses the DLL
>doesn't, or vice versa. Should one create both multi- and single-threaded
>versions and then use them as appropriate?

You'd have to dictate that the EXE is built with the multi-threading
version (assuming you are passing heap allocated objects between the
EXE/DLL of course).

Michael Winter

unread,
Sep 17, 2003, 3:22:25 PM9/17/03
to
Thanks. I've never found any reference, in the API or compiler documents,
that explains this sort of thing in black and white.

Dave Shawley

unread,
Sep 17, 2003, 10:59:40 PM9/17/03
to
"Michael Winter" <M.Winter@[no-spam]blueyonder.co.uk> wrote in message news:<Rv2ab.296$Gd.29...@news-text.cableinet.net>...

> Thanks. I've never found any reference, in the API or compiler documents,
> that explains this sort of thing in black and white.
>
> Mike

I wish that I had seen this post earlier... we've had the same problem at my
job. There are two solutions that we have come up with that seem to work
quite well:

1: The ``Draconian'' Approach
All code modules (exe's & dll's) must use the appropriate multi-threaded DLL
runtime. All debug modules must have an ``_d'' appended to the name before
the extension. All debug exe's must use _only_ debug components; all release
exe's must use _only_ release components.

2: The ``Pluggable Allocator'' Approach
All exe components that use a plug-in (DLL) component must export a general
allocator and deallocator to the plug-ins via an ``well-known'' initialize function
in the plug-in. All plug-ins must allocate _all_ memory that is passed to the exe
via the allocator and deallocate _all_ memory passed from the exe using the
deallocator.

Ultimately, we seem to have arrived at approach 1 after a bit of time. It is just
easier to do this whenever you have plug-ins that export classes and such.
Your mileage may vary though...

Enjoy!

Dave
--

0 new messages