1

I'm wondering about a situation where I'm trying to return a vector from DLL to .exe app. Compilers and settings for DLL and .exe app are the same. I know that passing STL vector through DLL boundaries might cause memory errors in case of alloc/dealloc memory.

What about the case when returning a vector wrapped by shared_ptr? Is this memory safe?

Little example:

exported DLL method:

__declspec(dllexport) std::shared_ptr<std::vector<MyObject>> MyDLL::myMethod()
{
    //Create object
    MyObject obj;
    std::vector<MyObject> myVector;
    myVector.push_back(obj);

    //Create wrapper
    std::shared_ptr<std::vector<MyObject>> spvObject = std::make_shared<std::vector<MyObject>>(myVector);

    return spvObject;
}

Get this data on .exe side:

MyDll dll;
std::shared_ptr<std::vector<MyObject>> objFromDll = dll.myMethod();

What will happen when pointer from .exe app will go out of scope? Will there be a memory error in case of deleting heap from DLL?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
drewpol
  • 665
  • 1
  • 6
  • 26
  • Edited, sorry for mistake. – drewpol Jan 11 '18 at 19:57
  • 1
    Then aside from creating temporary object and temporary vector on the stack and given that `MyObject ` has proper copy/move constructors and compiler/settings for caller and dll are the same this code will be ok. Also since (at least in this code snippet) ownership is not actually shared but transferred it would be better to use `unique_ptr`. – user7860670 Jan 11 '18 at 19:58
  • Does the DLL use that created vector internally? Based on the example, you could just return the vector by value. – Taylor Hansen Jan 11 '18 at 20:12
  • @TaylorHansen, in this case when `vector` from .exe goes out of scope my app crashes. This same happens when I use `unique_ptr. Only with `shared_ptr' it works fine. – drewpol Jan 11 '18 at 20:16
  • Then most likely there is something wrong with `MyObject` class, most likely missing / wrong constructors and assignment operators. – user7860670 Jan 11 '18 at 20:27
  • If you have control over the DLL and the applications that will be using it, make sure they all use the same CRT version and none of them statically link against the CRT. You shouldn't need a `shared_ptr` in that case, passing the `vector` by value should work. If that cannot be guaranteed, then I don't see how the `shared_ptr` can help either if the `vector` is modified by the DLL and the calling app both. – Praetorian Jan 11 '18 at 20:57

3 Answers3

0

So long as the EXE and DLL agree on the allocator being used passing objects across the boundary is okay, that is however a very big "if". It would be violated, for example, by re-building the EXE with a new compiler version but not re-building the DLL.

shared_ptr really doesn't change this, it merely ensures that the object will be deleted when no longer referenced, it has no bearing on what allocator will actually be used.

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
0

Well, the std::shared_ptr itself is safe, because it uses type-erasure on its allocator.

What isn't safe is the std::vector it owns, as that uses std::allocator directly, unless your EXE and your DLL agree on the definition of the latter, for example because they use the same shared runtime-library.
Wrapping it in a std::shared_ptr hasn't really changed anything.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

std::shared_ptr constructor can accept a 'Deleter', it will be stored inside the control block. Maybe appropriate deleter function in DLL will help with EXE/DLL boundaries?

BTW: std::vector can use custom allocator and it also can be customized to work in dll or exe address space.