www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - d malloc

reply "seany" <seany uni-bonn.de> writes:
consider this :

struct S
{
/* ... */

}

void main()
{
    ulong [] u;

    for(// ...
    {
       S s_instance;
       // fillup .. S.key = value;
       u ~= cast(ulong)*s_instance;
    }

}

however, the structs are being allocated to the same place. 
Because, Every time the iterator ends an iteration, seemingly, 
s_instance is collected as garbage.

A test produces output like this.
object : a of type : tensor is stored at : 140737373264752
object : b of type : tensor is stored at : 140737373264752
object : c of type : tensor is stored at : 140737373264752
object : d of type : tensor is stored at : 140737373264752

So I would like to know if there is a malloc alternative in D, 
which I can use to explicitely allocate memory to hold a struct, 
or any other variable , such that the garbage collector does not 
remove it automatically.
Aug 08 2014
next sibling parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Fri, Aug 08, 2014 at 04:42:12PM +0000, seany via Digitalmars-d-learn wrote:
 consider this :
 
 struct S
 {
 /* ... */
 
 }
 
 void main()
 {
    ulong [] u;
 
    for(// ...
    {
       S s_instance;
       // fillup .. S.key = value;
       u ~= cast(ulong)*s_instance;
    }
 
 }
 
 however, the structs are being allocated to the same place. Because,
 Every time the iterator ends an iteration, seemingly, s_instance is
 collected as garbage.
This has nothing to do with the GC. You're storing an address to a local variable on the stack, which is bad idea because once it goes out of scope, it will get overwritten by other data (such as subsequent instances of itself in the loop body). You need to explicitly allocate the struct on the heap with 'new' if you want it to survive past the end of the loop body: S* s_instance = new S(); u ~= cast(ulong)s_instance; Note that as long as you have pointers to the struct, the GC will not collect it. So you actually don't need to worry about freeing the data once you're done with it; just set all pointers to it to null, and the GC will collect it for you. T -- Why are you blatanly misspelling "blatant"? -- Branden Robinson
Aug 08 2014
parent reply "seany" <seany uni-bonn.de> writes:
On Friday, 8 August 2014 at 16:51:37 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Fri, Aug 08, 2014 at 04:42:12PM +0000, seany via 
 Digitalmars-d-learn wrote:
 consider this :
 
 struct S
 {
 /* ... */
 
 }
 
 void main()
 {
    ulong [] u;
 
    for(// ...
    {
       S s_instance;
       // fillup .. S.key = value;
       u ~= cast(ulong)*s_instance;
    }
 
 }
 
 however, the structs are being allocated to the same place. 
 Because,
 Every time the iterator ends an iteration, seemingly, 
 s_instance is
 collected as garbage.
This has nothing to do with the GC. You're storing an address to a local variable on the stack, which is bad idea because once it goes out of scope, it will get overwritten by other data (such as subsequent instances of itself in the loop body). You need to explicitly allocate the struct on the heap with 'new' if you want it to survive past the end of the loop body: S* s_instance = new S(); u ~= cast(ulong)s_instance; Note that as long as you have pointers to the struct, the GC will not collect it. So you actually don't need to worry about freeing the data once you're done with it; just set all pointers to it to null, and the GC will collect it for you. T
Okey, thank you. And as discussed earlier, I was trying to save the pointers in an ulong (which is same as size_t or ptr_t, those are aliased) array, but both addresses 7ff11330eeb0 and 7ff11330ed00 is saved as 140733974163440. What do I do?
Aug 08 2014
parent reply "anonymous" <anonymous example.com> writes:
On Friday, 8 August 2014 at 17:07:37 UTC, seany wrote:
 And as discussed earlier, I was trying to save the pointers in 
 an ulong (which is same as size_t or ptr_t, those are aliased)
(when compiling for x86-64 that is) Generally, casting pointers to size_t is a horrible idea. Why can't you at least go with void*?
 array, but both addresses 7ff11330eeb0 and 7ff11330ed00 is 
 saved as 140733974163440.

 What do I do?
Please show a proper self-contained test-case. That is, the code should compile as is, and show the problem (e.g. failing asserts, strange output).
Aug 08 2014
parent reply "seany" <seany uni-bonn.de> writes:
On Friday, 8 August 2014 at 17:44:29 UTC, anonymous wrote:
 On Friday, 8 August 2014 at 17:07:37 UTC, seany wrote:
 And as discussed earlier, I was trying to save the pointers in 
 an ulong (which is same as size_t or ptr_t, those are aliased)
(when compiling for x86-64 that is) Generally, casting pointers to size_t is a horrible idea. Why can't you at least go with void*?
I am very confused. Void* magically sorted a lot of problems out. Why are void pointers better than ulong, if I may ask (yes, I am on a x86-64)
Aug 08 2014
parent reply "ketmar" <ketmar ketmar.no-ip.org> writes:
 Why are void pointers better than ulong, if I may ask
there is at least one reason: GC. yes, it is conservative, but there's no reason to scan ulong[] for any pointers, so you may lost your objects if there is no other references to 'em.
Aug 08 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 8 August 2014 at 18:51:49 UTC, ketmar wrote:
 Why are void pointers better than ulong, if I may ask
there is at least one reason: GC. yes, it is conservative, but there's no reason to scan ulong[] for any pointers, so you may lost your objects if there is no other references to 'em.
And `ulong` is always 64 bits large, while pointer size depends on the system architecture (32 bits vs 64 bits). If you really, really must use an integral type instead of a pointer, use `size_t`, which is defined to have the same size as a pointer. But as ketmar said, the GC may not see recognize it then. `void*` also has the advantage that you don't need to case if you assign to it, because pointers convert to `void*` implicitly. In your case, however, you likely are better off if you use `S*`, then you don't need to do any conversions at all.
Aug 09 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 09 Aug 2014 09:08:14 +0000
via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 really must use an integral type instead of a pointer, use=20
 `size_t`, which is defined to have the same size as a pointer.
ptr_t or uptr_t ;-) that is the reason why the std.string.indexOf() using ptrdiff_t, for example.
Aug 09 2014
prev sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 08 Aug 2014 16:42:12 +0000
seany via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

a) we need the working code;
b) foreach (a; ...) doest struct copying, and you see the temporary
stack object as 'a'. either use 'ref a', or don't do that at all.

that is what i was able to understand from your code.
Aug 08 2014