Nesting a ref-struct instance within another, one of the properties of the nested object is corrupted upon manual garbage collection.
See this minimal code reproduction: https://github.com/hunterlester/minimum-ref-struct-corruption
Notice on the 3rd line of log output that the value of name is not corrupted:
Running garbage collection...
authGranted object afte gc: { name: '�_n9a\u0002', 'ref.buffer': <Buffer@0x00000261396F3910 18 86 6c 39 61 02 00 00> }
Unnested access container entry after gc: { name: 'apps/net.maidsafe.examples.mailtutorial', 'ref.buffer': <Buffer@0x00000261396F3B10 60 68 6e 39 61 02 00 00> }
Globally assigned values after gc: apps/net.maidsafe.examples.mailtutorial _publicNames
While
ref,ref-structandref-arrayare powerful, but fragile things, their combination can behave really obscure.There are two nuances with your sample:
Calling
makeAccessContainerEntrytwice overwrites your global cache -CStringscached (global.x0andglobal.x1) during themakeAuthGrantedFfiStructcall will be overwritten by the second directmakeAccessContainerEntrycall.It seems that you should cache each
ContainerInfoArraytoo.This code should work fine:
As you can see, I added cache to
makeAccessContainerEntryoutput, you should keep it somewhere as long as you need the data to be held from garbage collection.Edit: some background
JS implements high-level Memory Management where objects are referenced by references and memory gets released whenever there are no more references to the specific object.
In C there are no references and GC, but there are pointers which are simply memory addresses which point to the location where a specific structure or memory block is located.
refuses the following technique to bind these two: C pointer is a Buffer which stores the memory address where the actual data is located in memory. Actual data is usually is represented as a Buffer too.ref-structis an addon torefwhich implements the ability to interpret underlying memory blocks (Buffers) as structures - user defines types and how they are located in memory,ref-structattempts to read the corresponding portion of a memory block and obtain the value.ref-arrayis an addon torefwhich implements the ability to interpret underlying memory blocks (Buffers) as arrays - user defines types and how they are located in memory,ref-arrayattempts to read the corresponding portion of a memory block and obtain the array item.This way if you allocate a Buffer for something, then obtain a
refreference to it (a new Buffer that simply holds the memory address of the original Buffer) and lose the JS reference to the original Buffer, then the original Buffer could get released by GC like this:Do not hurry to test this code - both
console.log(refReference.deref());will print the same output becauserefholds a hidden reference to the referenceddatain therefReference.ref-structandref-arrayare aware of such situations and usually correctly hold hidden references to the referenced data too. But a combination ofref-structandref-arrayreveals a bug or an underlying incompatibility and hidden references sometimes get lost. A workaround is to cache references by yourself - that is the approach I suggested to use.