When an extern(C++) class is declared in D, but freed from C++, it calls the virtual deleting destructor. Currently DMD only calls the destructor, but does not free the memory, so this can cause silent memory leaks.
See TODO comment in DMD for Itanium ABI:
|
if (target.cpp.twoDtorInVtable) |
|
{ |
|
// TODO: create a C++ compatible deleting destructor (call out to `operator delete`) |
|
// for the moment, we'll call the non-deleting destructor and leak |
|
cldec.vtbl[cldec.cppDtorVtblIndex + 1] = cldec.dtor; |
|
} |
For Windows there is a similar TODO comment:
|
// // TODO: if (del) delete (char*)this; |
Previous discussion is in #8277.
There are different options to implement this:
- Directly calling
operator delete in the deleting destructor would be simple, but break code using extern(C++), but not using C++ new/delete.
- The deleting destructor could call a configurable callback in druntime, but this would not work with BetterC.
- A pragma or UDA could be used to enable/disable the deleting destructor. This would preserve backward compatibility, but users have to remember to do this, so memory is not leaked. In a future edition it could be enabled by default. The UDA/pragma could also be inherited by subclasses, so only a base class has to be marked.
I currently think a pragma would be best and will create a PR.
When an
extern(C++)class is declared in D, but freed from C++, it calls the virtual deleting destructor. Currently DMD only calls the destructor, but does not free the memory, so this can cause silent memory leaks.See TODO comment in DMD for Itanium ABI:
dmd/compiler/src/dmd/dsymbolsem.d
Lines 5985 to 5990 in 83c772b
For Windows there is a similar TODO comment:
dmd/compiler/src/dmd/clone.d
Line 1110 in 83c772b
Previous discussion is in #8277.
There are different options to implement this:
operator deletein the deleting destructor would be simple, but break code using extern(C++), but not using C++ new/delete.I currently think a pragma would be best and will create a PR.