how to pass a malloc'd C string over to be managed by the GC

Nicholas Wilson iamthewilsonator at hotmail.com
Thu Feb 28 04:54:10 UTC 2019


On Thursday, 28 February 2019 at 03:33:25 UTC, Sam Johnson wrote:
> ```
> string snappyCompress(const string plaintext) {
> 	import deimos.snappy.snappy : snappy_compress, 
> snappy_max_compressed_length, SNAPPY_OK;
> 	import core.stdc.stdlib : malloc, free;
> 	import std.string : fromStringz, toStringz;
> 	char *input = cast(char *) toStringz(plaintext);
> 	size_t output_length = 
> snappy_max_compressed_length(plaintext.length);
> 	char *output = cast(char *) malloc(output_length);
> 	if(snappy_compress(input, plaintext.length, output, 
> &output_length) == SNAPPY_OK) {
> 		string ret = (cast(string) fromStringz(output)).clone();
>                 // <---- do something magical here
> 		return ret;
> 	}
> 	assert(0);
> }
> ```
>
> How can I get the GC to automatically garbage collect the 
> `output` malloc call by tracking the returned `ret` reference?

I'm surprised that GC.addRoot(output) actually helped you here, 
GC.addRoot is for when the thing you are adding may hold pointers 
to GC allocated stuff and you don't want non-GC allocated 
references to dangle when the GC does a collection pass.

If you want the GC to handle it just use new:

char[] output = new char[output_length];
...
return assumeUnique(output);

> Or is this already managed by the gc because I cast to a 
> `string`?

No, string is just an alias for immutable(char)[], which is just
struct
{
     size_t length;
     immutable(char)* ptr;
}

it can refer to any span of memory, it has no concept of 
ownership.


More information about the Digitalmars-d-learn mailing list