www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - When this will be freed?

reply "Andrea Fontana" <nospam example.com> writes:
auto example(char* test) { return toStringz(to!string(test) ~ " 
world!"); }

When that return string will be freed?

What about:

extern(C) auto example(....)

?
Apr 02 2014
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-02 17:45, Andrea Fontana wrote:

 auto example(char* test) { return toStringz(to!string(test) ~ " world!"); }

 When that return string will be freed?
When there is no reference left to the string, the garbage collector is free to collect it when it chooses to.
 What about:

 extern(C) auto example(....)
Same as above, extern(C) does not change how memory is collected. If it is a C function, then it depends entirely on that particular function. -- /Jacob Carlborg
Apr 02 2014
parent reply "Andrea Fontana" <nospam example.com> writes:
On Wednesday, 2 April 2014 at 15:53:52 UTC, Jacob Carlborg wrote:
 On 2014-04-02 17:45, Andrea Fontana wrote:

 auto example(char* test) { return toStringz(to!string(test) ~ 
 " world!"); }

 When that return string will be freed?
When there is no reference left to the string, the garbage collector is free to collect it when it chooses to.
That's expected.
 What about:

 extern(C) auto example(....)
Same as above, extern(C) does not change how memory is collected. If it is a C function, then it depends entirely on that particular function.
I mean: if it is an exported function (of a shared library) what happens? There's no reference kept anywhere (in D). So if I'm right it could be freed immediatly by GC. Right?
Apr 02 2014
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 02.04.2014 17:57, schrieb Andrea Fontana:
 On Wednesday, 2 April 2014 at 15:53:52 UTC, Jacob Carlborg wrote:
 On 2014-04-02 17:45, Andrea Fontana wrote:

 auto example(char* test) { return toStringz(to!string(test) ~ "
 world!"); }

 When that return string will be freed?
When there is no reference left to the string, the garbage collector is free to collect it when it chooses to.
That's expected.
 What about:

 extern(C) auto example(....)
Same as above, extern(C) does not change how memory is collected. If it is a C function, then it depends entirely on that particular function.
I mean: if it is an exported function (of a shared library) what happens? There's no reference kept anywhere (in D). So if I'm right it could be freed immediatly by GC. Right?
If you pass that string to a C function, there is a reference on the stack. So this string will not be freed until that C-function returns. If that C-Function returns, it is very likely however that this was the only reference and the string will be freed the next time the garbage collector runs. Kind Regards Benjamin Thaut
Apr 02 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 2 April 2014 at 16:51:57 UTC, Benjamin Thaut wrote:
 Am 02.04.2014 17:57, schrieb Andrea Fontana:
 I mean: if it is an exported function (of a shared library) 
 what
 happens? There's no reference kept anywhere (in D). So if I'm 
 right it
 could be freed immediatly by GC. Right?
If you pass that string to a C function, there is a reference on the stack. So this string will not be freed until that C-function returns. If that C-Function returns, it is very likely however that this was the only reference and the string will be freed the next time the garbage collector runs.
This is unfortunately only true on x86 32-bit. For x86_64, the calling conventions (MS, SysV [1]) say that the first few parameters are passed in registers, and the same is probably true for other architectures. Usually this is still safe, as the pointer will normally either stay in its register, or will be spilled to the stack and kept there as long as the function still needs to use it. But one might imagine a corner case where it temporarily stores the pointer in a global or static variable. Even if the pointer will not be kept by the C function longer than the call, in such cases you would need to keep an additional reference where the GC can see it. [1] https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions
Apr 04 2014
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 04 Apr 2014 09:25:49 -0400, Marc Sch=C3=BCtz <schuetzm gmx.net> =
wrote:

 On Wednesday, 2 April 2014 at 16:51:57 UTC, Benjamin Thaut wrote:
 Am 02.04.2014 17:57, schrieb Andrea Fontana:
 I mean: if it is an exported function (of a shared library) what
 happens? There's no reference kept anywhere (in D). So if I'm right =
it
 could be freed immediatly by GC. Right?
If you pass that string to a C function, there is a reference on the =
=
 stack. So this string will not be freed until that C-function returns=
. =
 If that C-Function returns, it is very likely however that this was t=
he =
 only reference and the string will be freed the next time the garbage=
=
 collector runs.
This is unfortunately only true on x86 32-bit. For x86_64, the calling=
=
 conventions (MS, SysV [1]) say that the first few parameters are passe=
d =
 in registers, and the same is probably true for other architectures.

 Usually this is still safe, as the pointer will normally either stay i=
n =
 its register, or will be spilled to the stack and kept there as long a=
s =
 the function still needs to use it. But one might imagine a corner cas=
e =
 where it temporarily stores the pointer in a global or static variable=
. =
 Even if the pointer will not be kept by the C function longer than the=
=
 call, in such cases you would need to keep an additional reference whe=
re =
 the GC can see it.
In cases where it is stored in global data, and that becomes the only = reference, or if a C heap allocation is made, and the pointer is stored = in = there (perhaps to pass to another C function?), then it's quite possible= = the data could be collected prematurely in another thread. You bring up a good point. This is something that should be considered = when calling extern(C) functions. -Steve
Apr 04 2014
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-04 15:25, "Marc Schütz" <schuetzm gmx.net>" wrote:

 This is unfortunately only true on x86 32-bit. For x86_64, the calling
 conventions (MS, SysV [1]) say that the first few parameters are passed
 in registers, and the same is probably true for other architectures.
I'm not so familiar with calling conventions and how the stack and registers work. But take this as an example: extern (C) void foo (in char*); void bar () { string s = "asd"; foo(s.ptr); } Even if "s" is passed in a register to "foo", won't the stack of "bar" still be available until "foo" returns? -- /Jacob Carlborg
Apr 05 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 5 April 2014 at 11:28:36 UTC, Jacob Carlborg wrote:
 On 2014-04-04 15:25, "Marc Schütz" <schuetzm gmx.net>" wrote:

 This is unfortunately only true on x86 32-bit. For x86_64, the 
 calling
 conventions (MS, SysV [1]) say that the first few parameters 
 are passed
 in registers, and the same is probably true for other 
 architectures.
I'm not so familiar with calling conventions and how the stack and registers work. But take this as an example: extern (C) void foo (in char*); void bar () { string s = "asd"; foo(s.ptr); } Even if "s" is passed in a register to "foo", won't the stack of "bar" still be available until "foo" returns?
Yes, but it doesn't necessarily contain `s` anymore. Today's compilers are intelligent enough to see that `s` is never used after the function call, and therefore don't even allocate a stack slot for it. `foo` could be implemented like this (it's a C function, so `in` boils down to `const` without `scope`): char *b; void foo (const char *a) { b = a; // do something complex that causes all the registers to be reused // => the only reference to the string is now in b, outside of the GC's view // --> GC collects here <-- printf(b); // the string may have been collected here }
Apr 05 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-04-05 15:08, "Marc Schütz" <schuetzm gmx.net>" wrote:

 Yes, but it doesn't necessarily contain `s` anymore. Today's compilers
 are intelligent enough to see that `s` is never used after the function
 call, and therefore don't even allocate a stack slot for it.
Ok, I see.
 `foo` could be implemented like this (it's a C function, so `in` boils
 down to `const` without `scope`):

 char *b;
 void foo (const char *a) {
      b = a;
      // do something complex that causes all the registers to be reused
      // => the only reference to the string is now in b, outside of the
 GC's view
      // --> GC collects here <--
      printf(b); // the string may have been collected here
 }
Of course, if the C function is storing the parameter in a global variable you got problems. You really need to be sure of what the C functions is doing. To be on the safe side there's always GC.addRoot. -- /Jacob Carlborg
Apr 05 2014
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 2 April 2014 at 15:45:06 UTC, Andrea Fontana wrote:
 auto example(char* test) { return toStringz(to!string(test) ~ " 
 world!"); }

 When that return string will be freed?

 What about:

 extern(C) auto example(....)

 ?
to!string allocates on the GC heap when given a char* (it has to, in order to safely produce immutable data in the string). It will be freed by the first garbage collection ocurring after all references to that memory are dead.
Apr 02 2014