-1

I am newing a heap object in a regular DLL. I export it properly with __declspec(dllexport) and import it in the EXE with __declspec(dllimport) linkage. As long as I am in the DLL the object is defined properly, but when executing/debugging in the EXE, the object is undefined. What am I missing? Name mangling? Should extern "C" demangling help?

Further explanation: @Colin Robertson My problem stems from the prototype using extension DLLs whose code is integrated with the EXE upon compile. I knew my app would need to access objects directly in the DLL from the EXE which is okay in windows extension DLLs because of the code integration. But the prototype turned out to be a memory hog as my app creates many DLLs during execution, each of which got integrated, dynamically I might add, into the running executable. Therefore, the production code had to use the regular DLL which has automatic reference counting (dllmain etc) as long as it isn’t statically linked. Which brings me to my current problem of how do I access the DLL object from within the EXE?

As such, the discussion in your links regarding the passing of allocator is not relevant. Point 60 (60. Avoid allocating and deallocating memory in different modules.) in Sutter and Alexandrescu's book does not apply since the EXE is not responsible for object lifecyle. Also, since I am using shared libraries, the following is true: “Specifically, if you use the Dll runtime option, then a single dll - msvcrtxx.dll - manages a single freestore that is shared between all dll's, and the exe, that are linked against that dll.” (see StackOverflow’s “Who allocates heap to my DLL?” whose thread was closed by poke, Linus Kleen, mauris, Cody Gray, miku for some reason). My code does not mix the allocation/deallocation responsibilities of the DLL with the usage requests of the EXE.

I think the problem lies in the fact that in a regular DLL, using a pointer to an object in another module’s allocated heap running in a different thread with its own message pump is disastrous and is censured by the compiler. This is as it should be.

But my problem is still legitimate.

I see two ways windows solves such a situation. One is the Send/PostMessage call which posts messages on other thread queues and the other is COM marshalling. For the former I would have a problem with the return value. Since what I am doing is basically a remote procedure call, my EXE wants results back from the DLL, and SendMessage only returns an HRESULT. As for the latter, this is exactly what COM does when it marshals a pointer in an Apartment threaded app (see “Single-Threaded Apartments” in MSDN). COM is designed to let you pass pointers between threads, or even processes. There might be a third C++ way which is to use the Pimpl idiom (see http://www.c2.com/cgi/wiki?PimplIdiom), but this method is a lot more work and has drawbacks. Thanks to MVP Scott McPhillips for this suggestion.

Does anyone have advice or experience on which way to proceed?

rtischer8277
  • 496
  • 6
  • 27
  • Before I try to edit my answer, tell me whether you're using a static import library to link in your DLL, or if you call `LoadLibraryEx` instead. I'm also curious why you choose to have the DLL manage object lifetime, instead of letting the client construct objects defined in the DLL. Messaging is for separate processes, not (usually) communication with a DLL. COM is a better fit for generic interfaces and independent lifetime management, as you'd want for a plug-in interface. – Colin Robertson Aug 07 '15 at 21:52
  • While I'm asking clarifying questions, can you tell me what the debugger says about your object's lifetime, by setting breakpoints in the constructor and destructor? Mainly I'm curious if it's destroyed before the client ever sees it. – Colin Robertson Aug 07 '15 at 22:24
  • "using a static import library to link in your DLL, or if you call LoadLibraryEx" am using static import library. – rtischer8277 Aug 09 '15 at 14:38
  • "using a static import library to link in your DLL, or if you call LoadLibraryEx" am using static import library at compile time. At runtime I use AfxLoadLibrary. – rtischer8277 Aug 09 '15 at 15:30
  • If everything gets built as a single solution, with the same CRT, then in this case, once loaded at runtime, the DLL is effectively part of your .EXE image in memory. The heap is unfied. It's almost the same as linking to a static library. If the debugger loads all the symbols at startup, you'll be able to break anywhere and examine anything. There will only be one pass through your DLLMain at startup, and another when the app is torn down. You'll only see undefined symbols when the code is not there for some other reason, such as, it wasn't built. – Colin Robertson Aug 11 '15 at 23:09
  • Got it. In my architecture, however, there may be a dozen EXEs per machine. Is it not the case that the _tlid GUID for the DLL's registry entry would point to the same DllMain image code as for the other 11 running EXEs? So even though for each instance "There will only be one pass through your DLLMain at startup", there would cumulatively be 12 passes through the same DllMain code made accessible by the GUID. No? – rtischer8277 Aug 12 '15 at 12:00
  • I think there's confusion, and it might be mine. If you're implementing COM interfaces in your DLL, and you regserver them, then yes, there will be typelib info in the registry, but that's not what you get with a plain code DLL. Those just get looked up in the file system. As far as your EXE is concerned, the DLL's code is local to process memory, and its CRT-initialized static memory is unique to your process. You can't see what the OS might be doing with virtual pages for shared text segments. Each process only sees the one pass through DllMain at startup. – Colin Robertson Aug 13 '15 at 09:08

1 Answers1

-1

Don't do that. This is item 60 in Sutter and Alexandrescu's C++ Coding Standards book, which I highly recommend. Separate modules may use their own versions of the run time library, including the basic allocation routines. Things allocated on one module's heap may be inaccessible from another module, or have different conventions for allocating and freeing them. The name mangling conventions can be different, but that's the least of your worries. Here's another StackOverflow question that has more detailed answers for why this is a bad idea, and what to do instead: Is it bad practice to allocate memory in a DLL and give a pointer to it to a client app?

Community
  • 1
  • 1
Colin Robertson
  • 519
  • 1
  • 4
  • 8