Re: Odd behavior, vector member, MFC and consol app
Hi Doug, Joe, Giovanni,
(Got my fires out!)
I understand the issue you raise. I've given it some thought and done
some tracing.
It seems the original vector resides on the dll stack and the pointers
are created on the dll heap. In the destructor, as long as I use a dtor
defined in the dll space, they are destroyed there. The vector is
private so I don't have to worry about sharing in that sense. And, the
above seems to work fine even with an implicit copy constructor. Now the
copied vector will be in the app memory but on the stack, but the vector
memory is still on the dll heap. As long as I define the destructor in
the dll, the vector memory gets cleaned up there.
Also, the constructors are private. The app has no business creating
these, the CXML factory does this. So, there is no way the app can
create or modify this object with vector memory on the wrong heap.
Also, this class is not derived and because of the private constructors,
can not be derived from. As I understand it, virtual dtors are only
applicable if this were not the case.
I may still be breaking some rule, but I'm not sure what that is.
Best, Dan.
Doug Harrison [MVP] wrote:
On Sun, 12 Aug 2007 00:18:37 GMT, Dan Bloomquist <public21@lakeweb.com>
wrote:
Thanks Doug,
You made it easier to figure out and I learned something important about
the heap(s).
By putting:
XMLNODESET::~XMLNODESET( )
{
}
in the dll instead of just:
~XMLNODESET( ){ }
in the header, it forces destruction in the dll's heap and now it works.
Glad you got it to work. I'd still feel a little uneasy sharing C++ classes
that contain things like std::vectors between modules, when all the modules
aren't linking to the same CRT DLL. I'd at least want the class to use the
handle/body idiom, like this:
class X_EXPORT XMLNODESET
{
private:
class Impl;
public:
// Function declarations, nothing inline.
// All functions potentially generated by the compiler must be
// accounted for...
XMLNODESET();
~XMLNODESET();
void f();
private:
// Copyguard
//
// Here are the other two potentially compiler-generated functions.
// These are declared but never defined to rule out copying. If you
// want to support copying, move them to the public section and
// implement them.
XMLNODESET(const XMLNODESET&);
void operator=(const XMLNODESET&);
private: // Data section
Impl* p_impl;
};
Then in the DLL, it would be defined like this:
class XMLNODESET::Impl
{
public:
void f() {}
private:
std::vector<int> v;
};
void XMLNODESET::f()
{
p_impl->f();
}
This way, everything XMLNODESET objects do is done in the DLL, and
compilation dependencies have been minimized. In particular, all the
std::vector code is instantiated in the DLL, rather than some of it being
duplicated in the EXE, which would happen if XMLNODESET had inline
functions that used the vector. Note that if you're using different heaps,
you still have to worry about creating and deleting XMLNODESET objects in
the same context. (This is mitigated if XMLNODESET has a virtual dtor, and
X_EXPORT is __declspec(dllexport|dllimport) in the proper way, but this is
obscure, and I wouldn't rely on it.)