Re: Odd behavior, vector member, MFC and consol app
Doug Harrison [MVP] wrote:
On Tue, 14 Aug 2007 23:38:54 GMT, Dan Bloomquist <public21@lakeweb.com>
wrote:
Hi Doug, Joe, Giovanni,
(Got my fires out!)
I understand the issue you raise. I've given it some thought and done
some tracing.
Couple of things...
It seems the original vector resides on the dll stack and the pointers
are created on the dll heap.
There is no such thing as the "dll stack". Each thread has its own stack,
and it's used by all the code executing in that thread, wherever the code
actually lives, be it in a DLL or the EXE.
Hi Doug,
Thanks. Yes, I should know this stuff. The dll is just a code segment
and why it can be shared.
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.
I'm not sure what your code looks like, but it sounds something like this:
class X
{
private:
std::vector<int> v;
};
If you have an implicitly defined copy ctor, then you are able to copy the
vector. Unless the vector type is explicitly instantiated and exported,
this implies that the vector code is being instantiated wherever the copy
ctor is invoked. If this is indeed the case, and the default copy ctor
executes in the context of the EXE, the vector will be copied in that
context and use the EXE's heap for its allocations.
I've tried it explicit and implicit and seem to get the same results.
The copy occurs before returning from the xml.GetNodeSet call. I've
posted some code below.
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.
Depends on where the code for the vector copying resides.
And I'm confused as it seems different managers are in action. I just
don't know enough about it.
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.
I think chances are, you're OK, but it's hard to say for certain without
seeing the actual code. Some of these things are subtle and hard to convey
in plain English.
If you would really like to see it I'll zip the xml solution (7.1) and
upload it to the website. Add one to my email and I'll check that box
for the next couple of days. Here are some snippets:
This is with an implicit copy constructor, the copy occurs in the dll code.
in xml.GetNodeSet(...)
return set;
1002C506 lea eax,[set]
1002C509 push eax
1002C50A mov ecx,dword ptr [ebp+8]
1002C50D call XMLNODESET::XMLNODESET (10021009h)
1002C512 mov ecx,dword ptr [ebp-0ECh]
1002C518 or ecx,1
1002C51B mov dword ptr [ebp-0ECh],ecx
1002C521 mov byte ptr [ebp-4],1
1002C525 lea ecx,[xparse]
1002C52B call CXPath::~CXPath (10021D1Fh)
1002C530 mov byte ptr [ebp-4],0
1002C534 lea ecx,[set]
1002C537 call XMLNODESET::~XMLNODESET (100208E3h)
1002C53C mov eax,dword ptr [ebp+8]
}
The vectors _Myfirst is 0xdc1328
memory came from new.h
inline void *__cdecl operator new(size_t, void *_P)
{return (_P); }
10031540 push ebp
10031541 mov ebp,esp
10031543 mov eax,dword ptr [_P]
10031546 pop ebp
10031547 ret
Here I don't see any memory manager action?!
Now with an explicit copy constructor, and I've traced, it is getting
called, but now it uses malloc in afxmem.cpp
***
*this= inSet;
....
1002AF3C call XMLNODESET::operator= (1002014Ah)
}
....
--- No source file
-------------------------------------------------------------
XMLNODESET::operator=:
...
100292D1 call std::vector<TiXmlNode *,std::allocator<TiXmlNode
*> >::operator= (100209B0h)
...
};
afxmem.cpp:
void* __cdecl operator new(size_t nSize)
***
And _Myfirst is still 0xdc1328