Is It Bad Practice to Allocate Memory in a Dll and Give a Pointer to It to a Client App

Is it bad practice to allocate memory in a DLL and give a pointer to it to a client app?

Here are some reasons for having the caller supply a pointer:

  1. Symmetric ownership semantics. This is already explained by several other answers.
  2. Avoids mismatching the allocator and deallocator. As mentioned in Aesthete's answer, if the DLL allocates a pointer and returns it, the caller must call the corresponding deallocator to free it. This is not necessarily trivial: the DLL might be statically linked against one version of, say, malloc/free while the .exe is linked against a different version of malloc/free. (For example, the DLL could be using release versions while the .exe is using specialized debug versions.)
  3. Flexibility. If the DLL is meant for general use, having the caller allocate the memory gives the caller more options. Suppose the caller doesn't want to use malloc and instead wants memory to be allocated from some specific memory pool. Maybe it's a case where the caller could provide a pointer to memory allocated on the stack. If the DLL allocated the memory itself, the caller does not have any of these options.

(The second and third points also mostly can be addressed by having the .exe supply an allocator/deallocator for the DLL code to use.)

Memory allocation inside DLL returning null pointer

It was because I defined _USE_32BIT_TIME_T as preprocessor value.

I removed it and now it works fine.

Thanks everyone.

Is it possible to instantiate an object in a client if it's defined in a DLL/Lib?

In terms of heap allocation, I see no difference. In both cases, you get a class instance allocated on the heap. An instantiated object in the heap should take up the same amount of memory whether or not it was instantiated in them main executable, or a library.

In terms of code, I would expect to be a few bytes' worth of difference, between the two approaches. Background noise, nothing I would be concerned with.

C++ DLL interface and memory

No, it is not safe. There are three basic problems with using a DLL that exposes C++ code:

  • The DLL using different allocator. So your delete can't destroy the object. You already know about that one.

  • Your compiler not calculating the same layout for the class object. Particularly a problem if it has any members that are standard C++ library classes, like std::string or std::vector. That DLL could have been compiled with a different version of those classes. Like one that preceded C++11, it caused lots of changes in the std class implementations. Or used optimized release build settings and does not have iterator debugging enabled and you do.

  • Any exception objects that the DLL might throw across the module boundary suffer from the above two problems. This one is easy to overlook when you fix your DLL interface to be safe, you can't easily do the same thing for exceptions.

The second bullet is your nemesis, your compiler will compute the wrong size for the object and will not reserve the correct amount of space for it on the stack frame. Particularly nasty when the actual object size is larger, the code in the DLL will overwrite other variables on your stack. Pretty hard to diagnose.

Heap allocation failing in user DLL/EXE

Explicit Instantiation

Explicit Instantiation forces the compiler to generate code for a specific parameter list of a templated class or function. Without that code my imported DLL/EXE binaries were failing on runtime instantiations like ch = new char[ 100 ] and std::random_device rd; which implicitly does a global ::operator new. I have found no useful explanation for why this occurs. IPC discussions unfortunately don’t clearly distinguish between client-server runtime involving more than one running process, and runtime code that imports binary code (DLL/EXE) that was compiled and exported elsewhere.

The solution was to add a template parameter to the class that was failing and add a .cpp file to each module that explicitly instantiated the class, like MyClsModule1.cpp, MyClsModule2.cpp, etc. In these files I explicitly instantiate the class for that module. I also add the .h files, like MyClsModule1.h, MyClsModule2.h, for each module which contain externs so duplicate code generations don’t occur within a particular module. With this approach each module generates module-specific class code at compile time, which forces the module’s threads to allow heap instantiations which access that module’s process heap.

This modern C++ solution is elegant for me in that it keeps me from having to re-introduce complex IPC solutions like COM into my app code.

From an app developer’s perspective I think that my original code ought to have worked or at least have generated errors that were more informative as to what the problem was, so I am leaving my bug report mentioned in EDIT2 in effect.

Memory relocation for vector across DLL boundaries

The easiest way round this is to hide the vector inside methods exposed from the dll so you can get a const vector to view in other dlls, but not modify it. Then create a new function in dll B that adds the entry to the vector on the caller's behalf.

So your vector remains hidden inside dll B for all modifications.



Related Topics



Leave a reply



Submit