0

I have a dll with a class that uses an abstract class for customizing the behaviour and it also has an implementation defined in dll

With this the app allocates a Child object and passes it into the class A which it deallocates the object when it is deleted

Can deleting an object that is created in the app from the dll create a problem if it does any idea of fixing it

The code roughly translates into this

// Dll

DLLEXPORT class A
{
private:
   Base* ptr;
public:
   A(Base* ptr) { this->ptr = ptr; };
   ~A() { delete ptr; }
};

DLLEXPORT class Base
{
virtual int foo() = 0;
};

DLLEXPORT class Child : public Base
{
virtual int foo() { return 1; }
};
// App

int main()
{
    A obj(new Child);

    return 0;
}
  • 1
    Nag: in your example `Child` does not derive from `Base`. – user4581301 Mar 17 '22 at 20:19
  • I'm sure there is a duplicate for this, but in short, what if the object is allocated from a different heap in the DLL than the one used by the app? Bad things will happen if you attempt to `delete` that object. – PaulMcKenzie Mar 17 '22 at 20:24
  • Not 100% sure if this is necessary, but you should be able to implement the new/delete operator in a way that makes sure both the dll and the linking target allocate and deallocate memory in a compatible way... – fabian Mar 17 '22 at 20:26
  • [Possible duplicate, even though it talks about std::string](https://stackoverflow.com/questions/22279052/c-passing-stdstring-by-reference-to-function-in-dll). Especially take a look at the accepted answer, and the number `2)` item listed in the answer. – PaulMcKenzie Mar 17 '22 at 20:26

2 Answers2

1

MS says this:

The DLL allocates memory from the virtual address space of the calling process (docs)

And in this answer you can see:

If your DLL allocates memory using C++ functions, it will do so by calling operator new in the C++ runtime DLL. That memory must be returned by calling operator delete in the (same) C++ runtime DLL. Again, it doesn't matter who does that.

You can have trouble if the DLL, c++ runtime and/or app are compiled with a different compiler; or if some of those are compiled statically.

To avoid those problems, you can pass a "deleter" object/function to the DLL so it makes the deletion in the app:

DLL:

class Base;

typedef void (*deleter_t)(Base * ptr);

deleter_t app_deleter {nullptr};

DLLEXPORT class A
{
private:
   Base* ptr;
public:
   A(Base* ptr) { this->ptr = ptr; };
   ~A() { app_deleter(ptr); }
};

DLLEXPORT void set_deleter (deleter_t func)
{
   app_deleter = func;
}

APP:

void deleter (Base * obj)
{
  delete obj;
}

int main()
{
    set_deleter (deleter);

    A obj(new Child);

    return 0;
}

More details at: SO answer SO answer

Manuel
  • 2,526
  • 1
  • 13
  • 17
-1

You can follow the Cpp Core Guidelines conventions to specify the transfere of ownership of the resource to make it clear what happens.

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rr-owner

There is also a lot of other good guidelines in there, like using initialization instead of assignment of member variables.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
  • 2
    I don't think the question is about transferring ownership, but about whether memory allocated inside the dll can safely be freed by the target linking the dll. – fabian Mar 17 '22 at 20:24
  • @fabian You got that backwards. The DLL frees the memory, the app allocates it. And the answer to when that is a problem is exactly the question about transfer of ownership (assuming the DLL is using the same new/delete at all). – Goswin von Brederlow Mar 18 '22 at 23:37