I'm currently using kotlin 1.7.20 and the new memo...
# kotlin-native
u
I'm currently using kotlin 1.7.20 and the new memory management model, but when I use native to interop with my c library, I can't seem to make good use of the gc, such as when I call createLinkedList() in the c library I guess the new memory management model cannot help me completely free the memory of the linked list during gc, does it mean that I can only manage the memory manually, is there any way to automatically call freeLinkedList() during gc?
I'm writing kotlin native to c library bindings, and for my users, they probably don't understand why kotlin is based on gc but needs to manage memory manually
j
The Kotlin/Native memory manager manages memory for Kotlin objects, but not memory allocations from C APIs. You can use tools like memScoped, Arena, and createCleaner to manage memory you allocate through C APIs, or by manually calling
malloc()/free()
.
u
@Jeff Lockhart Thanks for such a quick reply. Yes I use memScoped and Arena a lot in my projects. Does this mean that I still need to provide an exposed clear method for the user to call at the right time?
l
You would need to expose a clear method if you use arena. If you only need memory within a function, memScoped cleans all its memory up when the lambda ends execution (be careful not to save any pointers allocated in memScoped), and cleaner lets the GC tell us treat the C object like a Kotlin object in terms of memory (be careful passing this to a C function, as Kotlin still needs a reference or the variable must be pinned to make sure the GC doesn’t collect it). 3 different tools for 3 different uses.
j
That's a good summary of how each tool accomplishes different needs. I've also used arenas in conjunction with cleaners, where a Kotlin object allocates memory via the arena and clears the arena in the cleaner. My project is a KMP bindings library, with the goal of maintaining a consistent KMP API, without requiring specific native memory management primitives. I've found I can accomplish this in the native C platforms with careful usage of Kotlin objects to bind the lifecycle of underlying native memory. As Landry mentioned, you have to be careful that the Kotlin object is retained properly for the underlying native memory lifecycle, as when the Kotlin object is GCed, the cleaner will release the native memory. I've been able to avoid the need to expose memory clear methods in the API though.
l
If you want to use cleaner, and need to mark that C code needs it, but Kotlin won’t have a reference, pinning the pointer and unpinning after the C code is done will work.
u
Your answers have inspired me a little bit, I think in my usage scenario, I may need to distinguish whether the c struct point I get is read-only or writable, if for read-only variables I can put it in the memScoped block scope Free the c pointer after all variables are converted to kotlin objects, but if it is a writable c pointer, I may need to keep the c pointer and provide a clean method