Re: DLL pass vector by value crash

Tech-Archive recommends: Fix windows errors by optimizing your registry



Well, I can't see why the issue of common heap and allocator (operator
new/malloc in this case) hasn't been pushed harder here, so I'll do
it.

Presuming that you build your exe and dll with same compiler and same
compiler options, your code should work. Since it does not... It is
crucial to remember and obey the most common and most glaring issue
when using DLLs:

drum roll....

heap (allocation) for stuff allocated in one module and de-allocated
in another must be one and the same (root of that being how operator
new/delete are specified to work).


That is absolutely the first thing to observe. (Second is potential
incompatibility in compiler options between two executables, which
AFAIK plays because we are talking about code generated from
templates. But that's not my bet here).

Now, in your code, you create a vector and populate it. That involves
heap allocation. That you pass it by value, _does_not_matter_, because
copy is still made in the same module, the exe, prior to going to the
dll. So your exe allocates stuff through vector or string member
functions. Allocations are made on the heap __of__the__exe__. Then you
pass said vector to the dll. If the dll uses the vector so that
allocation functions are called (e.g. v.push_back), that allocation is
made on the heap __of__the__dll__. Once you get out of the dll call,
vector gets destroyed (it's a temporary copy of your variable, but
again, that does not matter in the slightest). Destruction involves,
in your case, freeing stuff of the heap. If the heap of the exe and
the heap of the DLL are not one and the same, that
___can_not_possibly_work___!

One hard, but not so fast, method to check that you indeed have
correct heap: allocation functions (new, delete, malloc, free) must be
one and the same in both modules. Here's how you could verify this:

Modify your exe and your dll so that you have at least one heap
allocation in both. To do that, for example, call operator new for
anything (e.g. new int;) in both your exe and in your dll. Debug this.
Go into said "new" (afxmem.cpp, 346 here), and in dissasembly window,
note the starting address. If it's not the same when called from the
*.exe and from *.dll, you are DOA.

If indeed you have two "news", check what CRT/MFC modules you have
loaded (or check module dependencies). Check also that you don't link
exe or dll statically to CRT/MFC.

AFAIK, there is __only_one_method__ to have good heap: use same CRT
and MFC in both modules __and__ link to corresponding CRT/MFC DLLs
from both modules. And that means __same_version__ of CRT/MFC dlls,
too! Only that ensures that operator new/delete and malloc/free are
one and the same, and that there is only one heap - that of shared CRT/
MFC module.

That said... That is horribly constraining. I mean, what is the
purpose of having separate modules, when they have to share compiler,
(probably) compiler options, and CRT/MFC versions? Only in-house code
sharing, and even then, it opens deployment issues: upon CRT updates,
two modules must be deployed together.

If in-house is what you are doing and don't mind deployment-wise, then
OK.

If not, __just__effin__change__right__now! Change to what, you might
ask, and there, you have two options I can think of:

1. use straight C interface for the DLL and in it, have special
DLLAlloc/DLLFree function that must be used for heap-allocated
exchanged stuff (or perhaps more of these^^^).
2. use COM (I'd personally always go for COM because it's a much
richer interfacing environment than pure C)

Goran.

^^^ E.g. if using "opaque C classes" with following interface visible
from the DLL:

typedef struct X; // Don't show definition of X to clients - C
encapsulation is __strong__, yay!
X* initX(params); // Let's call this "C ctor" :-)
ret op1(X* pThis, params);
ret op2(X* pThis, params);
ret op3(X* pThis, params);
void freeX(X*); // "C dtor"
.



Relevant Pages

  • Re: DLL pass vector by value crash
    ... stack of the exe and may allocate default member element on the exe heap. ... If this is a dangerous situation, the simple app I set up calling testFunc() ... in a dll did not crash. ...
    (microsoft.public.vc.mfc)
  • Re: SysAllocString
    ... DLL, for both EXE and DLL), then I think you willl have no problem. ... Visual Studio 2003 with another CRT (e.g. statically linked CRT, ... The correct thing to do would be to expose *both* allocation and freeing by ...
    (microsoft.public.vc.language)
  • Re: passing using "string" type in DLL Interface
    ... Since string is a dynamic data structure allocated on the heap there ... the .exe and .dll are compiled with different versions of the compiler ... same compiler and library versions so we have no problem passing any SCL ...
    (microsoft.public.vc.stl)
  • _CrtIsValidHeapPointer problem while exporting dll vc6.
    ... I am facing a problem while exporting a dll ... which uses the std::string, in to an exe. ... the destructor this error is occured. ... be asserting using the dll's heap there should not be any problem. ...
    (microsoft.public.vc.stl)
  • Re: heap shared with DLL
    ... If you statically link the C runtime to both an EXE and a DLL, there is no guarantee that memory allocated via the EXE's mallocimpelementation can be freed by the DLL's freeimplementation. ... In any case, in WinNT/2K/XP and in WinCE heaps are process-owned, and the heap manger maintains alloc/free states of blocks. ... In early WinCE MS CRT lib, these were straight calls to LocalAlloc/LocalFree, so worked off the main process heap. ...
    (microsoft.public.windowsce.embedded)