digitalmars.D.learn - Mem Mgmt: With & Without the GC
- Zane (24/24) Aug 21 2016 Hey all,
- Cauterite (7/9) Aug 21 2016 I can answer this at least,
- Zane (14/23) Aug 21 2016 I see - That makes sense, but is there no way to "pause/stop" the
- Cauterite (33/38) Aug 21 2016 Oh you can use `new` when the GC is disabled, no problem. All the
- Cauterite (6/8) Aug 21 2016 All the allocation/deallocation functionality is the same as
- Cauterite (9/12) Aug 21 2016 Because the GC is not of the incremental type, it can't perform
- Cauterite (5/7) Aug 21 2016 While my earlier suggestion of using malloc/emplace is one
- Cauterite (12/15) Aug 21 2016 The main problem is that `new` does not necessarily give you a
- Guillaume Piolat (30/54) Aug 21 2016 If you need to destroy a class object right now, the proper way
- Zane (3/3) Aug 21 2016 Thanks to both of you. I think that answers everything, except if
- Mike Parker (3/7) Aug 21 2016 Or just tell the GC directly not to collect it via GC.addRoot:
Hey all, My knowledge of GCs is limited, but my faith in them (for most applications) has greatly increased with advances (like with Golang's recent updates). I am now trying to get a better sense for the direction D is going regarding memory management, both in relation to the GC and without it. Excuse my ignorance, but can someone clarify the following for me? 1) If using the GC, but for whatever reason, I need to free something _right now_, is core.GC.free() the proper way to do this? 2) Does calling object.destroy() mean that the object is marked for future collection? If not, how can I ensure it is properly marked. 3) How can I mark a non-object for future collection? For example, a dynamic array: int[] a = new int[10];. Do I just set any references to null? 4) What if I want to immediately deallocate a dynamically allocated non-object (such as the dynamic array) - Can I use core.GC.free? 5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to? 6) If the GC is off, how is allocation/deallocation handled? Can I still use new for example (and how do I dealloc)? Thank you for any help you can provide.
Aug 21 2016
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to?I can answer this at least, If you don't want the GC to ever collect the object itself, here's the best way: Allocate the object with a non-GC allocator (such as std.c.malloc ), then use `emplace` to construct the object in that memory (
Aug 21 2016
On Sunday, 21 August 2016 at 16:38:09 UTC, Cauterite wrote:On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:I see - That makes sense, but is there no way to "pause/stop" the GC, but still be able to use the 'new' syntax? I like how clear the syntax is, I just don't _always_ want the GC. I'm thinking of something like: core.memory.GC.disable(); Obj o = new Obj(); /* ...use o... */ core.memory.GC.free(o); // or whatever if possible, is there a drawback to this (other than no automatic GC) compared to say, malloc? Regarding the marking, I guess my question is: what must be done to ensure something allocated with 'new' will be a candidate for auto-collection later (when GC is enabled)?5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to?I can answer this at least, If you don't want the GC to ever collect the object itself, here's the best way: Allocate the object with a non-GC allocator (such as std.c.malloc ), then use `emplace` to construct the object in
Aug 21 2016
On Sunday, 21 August 2016 at 18:31:26 UTC, Zane wrote:I see - That makes sense, but is there no way to "pause/stop" the GC, but still be able to use the 'new' syntax?Oh you can use `new` when the GC is disabled, no problem. All the GC's functionality is still available. But be careful about what I said with `new` not returning the base of the allocation. It might not be safe to explicitly `free()` memory allocated by `new` if there could be multiple objects in the same memory block. I honestly don't know the facts about this. You can always `GC.free()` memory you've allocated yourself with `GC.malloc()`, so malloc+emplace is an option. You could define a template to give more convenient syntax. Also I think you can overload the `new` operator. I've never tried it.Regarding the marking, I guess my question is: what must be done to ensure something allocated with 'new' will be a candidate for auto-collection later (when GC is enabled)?I don't think it's possible with a conservative garbage collector, because anything that looks like a pointer to your object can prevent it from being collected. However, if there are no actual live pointers to it, the chances that it will be collected are very high, especially on 64-bit systems. So for now, your best bet is to make sure your object is not accessible (set all live pointers to it to null). It will only stay in memory if you're very unlucky. Once we have a precise garbage collector (should be soon) you can be sure an object will get collected if it is not accessible from any live pointers. -------------------------------------- By the way, when I say "live pointer", I mean a pointer which is accessible (through any number of indirections) from the memory roots. e.g. If you have a linked list on the heap, with each node pointing to the next, but no other pointers to any of the nodes (e.g. from the stack) those pointers are not live. The list as a whole is not accessible.
Aug 21 2016
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:6) If the GC is off, how is allocation/deallocation handled? Can I still use new for example (and how do I dealloc)?All the allocation/deallocation functionality is the same as normal, except the GC won't start a collection cycle unless it's out of memory. You can still use `free()` to deallocate, and it will free memory straight away.
Aug 21 2016
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:2) Does calling object.destroy() mean that the object is marked for future collection? If not, how can I ensure it is properly marked.Because the GC is not of the incremental type, it can't perform any marking outside of a stop-the-world mark/sweep cycle. Instead, what `destroy()` does is finalise an object: that is, runs any destructors and puts it in an invalid state — in particular, all pointers contained within the object are nullified, so it doesn't reference any other objects. When I say 'object' I mean anything; class instance, structure, array, primitive, whatever.
Aug 21 2016
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to?While my earlier suggestion of using malloc/emplace is one option, another is to use `GC.addRoot(objPtr)`. It ensures the object is never deallocated until you call `GC.removeRoot(objPtr)`.
Aug 21 2016
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:1) If using the GC, but for whatever reason, I need to free something _right now_, is core.GC.free() the proper way to do this?The main problem is that `new` does not necessarily give you a pointer to the start of an allocation, and `GC.free()` does not work if you give it a pointer to the interior of an allocated block. You could use `GC.addrOf()` to get the base address from an interior pointer, but I don't know whether there could be other objects/arrays sharing the same memory block. If you explicitly allocated the memory block yourself with `GC.malloc()` then you have full control over what is placed in it and can safely `GC.free()` the memory using the base address. Keep in mind, `GC.free()` does not call finalisers.
Aug 21 2016
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote:Hey all, My knowledge of GCs is limited, but my faith in them (for most applications) has greatly increased with advances (like with Golang's recent updates). I am now trying to get a better sense for the direction D is going regarding memory management, both in relation to the GC and without it. Excuse my ignorance, but can someone clarify the following for me? 1) If using the GC, but for whatever reason, I need to free something _right now_, is core.GC.free() the proper way to do this?If you need to destroy a class object right now, the proper way is to call .destroy on it (or use something that uses it like Scoped!T, Unique!T, Refcounted!T...). If you need to destroy a struct object right now, the proper way is to end the scope. If you need to free memory right now, better not allocate it from the GC, but instead with malloc/free. The GC does not guarantee to collect freed memory when you want.2) Does calling object.destroy() mean that the object is marked for future collection? If not, how can I ensure it is properly marked.Calling .destoy on an object calls its destructor but does not mark it for collection. Objects are collected when they are not reachable anymore. At this point, the destructor is called if it wasn't already (and then the object is overwritten with .init). Actually you shouldn't have to worry when an object memory is collected.3) How can I mark a non-object for future collection? For example, a dynamic array: int[] a = new int[10];. Do I just set any references to null?Yes, it is marked for future collection when it's not reachable anymore. Then again, the GC might not reclaim memory right now because it's imprecise and you could have "false pointers".4) What if I want to immediately deallocate a dynamically allocated non-object (such as the dynamic array) - Can I use core.GC.free?I don't know if this will deallocate with 100% certainty.5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to?Keep a reference somewhere reachable (by default: stack, heap, globals: everything is reachable and scanned).6) If the GC is off, how is allocation/deallocation handled?If you have called GC.disable, no GC collect is performed on any allocation. This is only suitable if you don't have a long-running software that would risk running out of memory. This is known to speed-up short processes.Can I still use new for exampleYou can still use new.(and how do I dealloc)?I don't know then if you can deallocate.
Aug 21 2016
Thanks to both of you. I think that answers everything, except if new'd objects can be freed when GC is disabled. I guess I could always enable and call collect().
Aug 21 2016
On Sunday, 21 August 2016 at 19:30:51 UTC, Guillaume Piolat wrote:Or just tell the GC directly not to collect it via GC.addRoot: https://dlang.org/phobos/core_memory.html#.GC.addRoot5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to?Keep a reference somewhere reachable (by default: stack, heap, globals: everything is reachable and scanned).
Aug 21 2016