Open haelue opened 11 months ago
Smart pointers will automatically be cleaned up when garbage collected, but it's still recommended you called delete on them. See https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#memory-management
Smart pointers will automatically be cleaned up when garbage collected, but it's still recommended you called delete on them. See https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#memory-management
So the warning "Embind found a leaked C++ instance Random <0x000113d8>" in browser console (chrome), means the garbage collect is invoking smart pointer clean-up?
So the warning "Embind found a leaked C++ instance Random <0x000113d8>" in browser console (chrome), means the garbage collect is invoking smart pointer clean-up?
Yes, but that doesn't work reliably and might not work at all in some browsers. That's why manual .delete()
is necessary for now.
This is similar to other usecases that require manual cleanup in JS - e.g. closing files in Node.js or other examples listed in https://github.com/tc39/proposal-explicit-resource-management. In the future we should be able to leverage that proposal to at least provide a nicer syntax for this, as in, you will be able to write
using embindObj = new EmbindClass();
and it will be freed upon exit from scope, but for now manual .delete()
is the way to go.
Yes, but that doesn't work reliably and might not work at all in some browsers. That's why manual
.delete()
is necessary for now.
Is that still the case for recent browsers or are there still issues?
Is that still the case for recent browsers or are there still issues?
It is because that check uses FinalizationRegistry which, per spec, is not guaranteed to run either anytime soon or ever (and, indeed, will not run under some GC flags). Which makes it useful for eventual cleanup and leak detection if user forgot to do so manually, but not a full replacement for a deterministic cleanup.
It can be especially problematic if C++ class owns external resources (files / databases / etc) or if C++ objects need to be dropped in predetermined order (which is somewhat common in native code where one object holds references to another and wrong destructor order can lead to memory corruption).
It is because that check uses FinalizationRegistry which, per spec, is not guaranteed to run either anytime soon or ever (and, indeed, will not run under some GC flags).
By flags, do you mean a flag to not collect at all? I agree we won't get callbacks in that case, but then I think it's the expected behavior.
It can be especially problematic if C++ class owns external resources (files / databases / etc) or if C++ objects need to be dropped in predetermined order
This sounds like a serious problem that I hadn't considered. It seems like this means C++ and Rust and all other languages using some form of deterministic ordered destruction can't work without manual destruction in JS..?
same issue here
By flags, do you mean a flag to not collect at all?
Either not collect at all, or simply high GC limits (which are configurable in JS engines) which will also cause GC to never be hit. In that scenario it will also vary on the device, available memory and so on, becoming pretty hard to debug.
It seems like this means C++ and Rust and all other languages using some form of deterministic ordered destruction can't work without manual destruction in JS..?
Yes, deterministic destruction is exactly why tc39/proposal-explicit-resource-management is being proposed even though FinalizationRegistry already exists. I believe it will cover those cases better.
For some (most?) usecases users can still use FinalizationRegistry on per-class basis if they're sure it's fine for the given class to run destructor out of order or not run it at all, I'm just saying it shouldn't be the default but rather an explicit opt-in. Maybe as a new Embind annotation?
I use embind and .smart_ptr_constructor() to bind a C++ class.
I suppose a smart-pointer could help me to write javascript easy without calling .delete(), but the browser console still warning:
Since .delete() is easily interrupted by exception or something else, how can I use emscripten really safe and concise?
My C++ header:
My C++ soure:
My embind wrapper:
My build command:
My javascript test: