digitalmars.D.learn - How to free memory ater use of "new" to allocate it.
- Alain De Vos (22/22) Jul 16 2023 I don't use malloc
- Richard (Rikki) Andrew Cattermole (4/4) Jul 16 2023 You can do it with ``GC.free``.
- Alain De Vos (10/10) Jul 16 2023 Is this ok ?
- Richard (Rikki) Andrew Cattermole (4/4) Jul 16 2023 Yes.
- Steven Schveighoffer (17/27) Jul 16 2023 No, that won't work. Check out `i` value after you call `destroy` on it:
- Alain De Vos (20/20) Jul 16 2023 The following program prints two different addresses.
- Alain De Vos (24/24) Jul 16 2023 Maybe code above works when you enforce an Garbage-collection-run
- Steven Schveighoffer (4/34) Jul 17 2023 Notice how you didn't call `destroy(a)` there. If you did, then
- Steven Schveighoffer (5/32) Jul 17 2023 No, what I am trying to explain is that `destroy(a)` is literally
- Richard (Rikki) Andrew Cattermole (2/2) Jul 16 2023 Steven is right, was quite late when I said that so it'll work but not
- Alain De Vos (31/31) Jul 17 2023 The following code works:
- drug007 (3/44) Jul 17 2023 Note that you do not use new anymore. You allocate your class instances
- Alain De Vos (28/28) Jul 17 2023 This works also:
- drug007 (6/11) Jul 17 2023 Despite this time you use new you still allocate your class on stack
- Alain De Vos (28/28) Jul 17 2023 Here is i use new,
- Nick Treleaven (24/29) Jul 17 2023 Firstly, be careful with class destructors and GC managed
- Alain De Vos (23/23) Jul 17 2023 This works also,
- Ernesto Castellotti (2/25) Jul 17 2023 Remember to use free, this is not managed by the GC
I don't use malloc ``` import std.stdio: writeln; 2 │ 3 │ class C{ 4 │ int[] i=null; 5 │ this(){ 6 │ writeln("Allocate heap"); 7 │ i=new int[10000]; 8 │ writeln(typeid(typeof(i))); 9 │ writeln(typeid(typeof(i.ptr))); 10 │ i[9000]=5; 11 │ } 12 │ ~this(){ 13 │ writeln("Free heap"); 14 │ import object: destroy; 15 │ import core.memory: GC; 16 │ i=null; // But How to force GC free ? -------------? 17 │ }; 18 │ } ```
Jul 16 2023
You can do it with ``GC.free``. But you really shouldn't need to (it won't automatically release it back to OS). https://dlang.org/phobos/core_memory.html#.GC.free
Jul 16 2023
Is this ok ? ``` void main(){ int[] i=new int[10000]; import object: destroy; destroy(i); import core.memory: GC; GC.free(GC.addrOf(cast(void *)(i.ptr))); } ```
Jul 16 2023
Yes. For basic types like int's, you don't need to destroy the array. As long as you don't slice the array and store that in i, you don't need to call addrOf too.
Jul 16 2023
On 7/16/23 2:41 PM, Alain De Vos wrote:Is this ok ? ``` void main(){ int[] i=new int[10000]; import object: destroy; destroy(i); import core.memory: GC; GC.free(GC.addrOf(cast(void *)(i.ptr))); } ```No, that won't work. Check out `i` value after you call `destroy` on it: ```d destroy(i); // basically sets i = null assert(i.ptr is null); // yep GC.free(i.ptr); // basically free(null) which is a no-op ``` Also note that `destroy` is *shallow*. It does not dig into pointers or arrays. So even if your array was of elements with a destructor, destroying the array doesn't destroy the elements. In this case, all you need to do is: ```d GC.free(GC.addrOf(i.ptr)); ``` You don't need the cast here. You shouldn't need the addrOf, but this is still open: https://issues.dlang.org/show_bug.cgi?id=13558 -Steve
Jul 16 2023
The following program prints two different addresses. Meaning the new allocates memory until the program dies. So the means memory leak by default ? ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; void dofun(){ auto a=new int[1000]; writefln("%12x",&a); destroy(a); GC.free(a.ptr); } int main(){ dofun(); auto b=new int[1000]; writefln("%12x",&b); return 0; } ```
Jul 16 2023
Maybe code above works when you enforce an Garbage-collection-run ? Code below works fine. So you cannot use "new" but must use malloc? ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; import core.stdc.stdlib: malloc,free; void dofun(){ auto pa=cast(int *)malloc(1000*int.sizeof); writefln("%12x",pa); auto a=pa[0..1000]; free(a.ptr); } int main(){ dofun(); auto pb=cast(int *)malloc(1000*int.sizeof); writefln("%12x",pb); auto b=pb[0..1000]; free(b.ptr); return 0; } ```
Jul 16 2023
On 7/16/23 11:58 PM, Alain De Vos wrote:Maybe code above works when you enforce an Garbage-collection-run ? Code below works fine. So you cannot use "new" but must use malloc? ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; import core.stdc.stdlib: malloc,free; void dofun(){ auto pa=cast(int *)malloc(1000*int.sizeof); writefln("%12x",pa); auto a=pa[0..1000]; free(a.ptr); } int main(){ dofun(); auto pb=cast(int *)malloc(1000*int.sizeof); writefln("%12x",pb); auto b=pb[0..1000]; free(b.ptr); return 0; } ```Notice how you didn't call `destroy(a)` there. If you did, then `free(a)` would be equivalent to `free(null)`, which would do nothing. -Steve
Jul 17 2023
On 7/16/23 11:41 PM, Alain De Vos wrote:The following program prints two different addresses. Meaning the new allocates memory until the program dies. So the means memory leak by default ? ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; void dofun(){ auto a=new int[1000]; writefln("%12x",&a); destroy(a); GC.free(a.ptr); } int main(){ dofun(); auto b=new int[1000]; writefln("%12x",&b); return 0; } ```No, what I am trying to explain is that `destroy(a)` is literally equivalent to `a = null`. If you then `free(a)` do you think it does anything? -Steve
Jul 17 2023
Steven is right, was quite late when I said that so it'll work but not for the reasons I thought it would.
Jul 16 2023
The following code works: ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; import core.stdc.stdlib: malloc,free; import std.typecons; class C { int * pa; int [] a; // Constructor this() {writefln("Called constructor"); pa=cast(int *)malloc(1000*int.sizeof); a=pa[0..1000]; } ~this(){ writefln("Called Destructor"); free(a.ptr);} } void dofun() { auto x=scoped!(C); x.a[3]=5; writefln("%12x",&x); } int main(){ dofun(); dofun(); return 0; } ```
Jul 17 2023
17.07.2023 13:17, Alain De Vos пишет:The following code works: ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; import core.stdc.stdlib: malloc,free; import std.typecons; class C { int * pa; int [] a; // Constructor this() {writefln("Called constructor"); pa=cast(int *)malloc(1000*int.sizeof); a=pa[0..1000]; } ~this(){ writefln("Called Destructor"); free(a.ptr);} } void dofun() { auto x=scoped!(C); x.a[3]=5; writefln("%12x",&x); } int main(){ dofun(); dofun(); return 0; } ```Note that you do not use new anymore. You allocate your class instances on stack and their scope is `dofun()` only
Jul 17 2023
This works also: ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; import core.stdc.stdlib: malloc,free; import std.typecons; class C { int * pa; int [] a; // Constructor this() {writefln("Called constructor"); pa=cast(int *)malloc(1000*int.sizeof); a=pa[0..1000]; } } void dofun() { scope x=new C; x.a[3]=5; writefln("%12x",&x); } int main(){ dofun(); dofun(); return 0; } ```
Jul 17 2023
17.07.2023 15:45, Alain De Vos пишет:This works also: [snipped]Despite this time you use new you still allocate your class on stack using scope and its scope still is `dofun`. But I just want to inform you. Your solutions work. Don't get me wrong. N.B. I would say if you do not have THE reason to manually free memory - do not do this. At all. Just let GC does its work.
Jul 17 2023
Here is i use new, ``` import std.stdio:writefln; import object: destroy; import core.memory: GC; import core.stdc.stdlib: malloc,free; import std.typecons; class C { int * pa; int [] a; // Constructor this() {writefln("Called constructor"); pa=cast(int *)malloc(1000*int.sizeof); a=pa[0..1000]; } } void dofun() { scope x=new C; x.a[3]=5; writefln("%12x",&x); } int main(){ dofun(); dofun(); return 0; } ```
Jul 17 2023
On Sunday, 16 July 2023 at 18:18:08 UTC, Alain De Vos wrote:12 │ ~this(){ 13 │ writeln("Free heap"); 14 │ import object: destroy; 15 │ import core.memory: GC; 16 │ i=null; // But How to force GC free ?Firstly, be careful with class destructors and GC managed objects. The memory referenced by `i` may already have been freed by the GC when the class destructor is called - see: https://dlang.org/spec/class.html#destructors If you want to free GC memory when you know the allocation is still live, you can call __delete: https://dlang.org/phobos/core_memory.html#.__delete import std.stdio: writeln; ```d void main() { int[] i=null; writeln("Allocate heap"); i=new int[10000]; i[9000]=5; import core.memory; const p = i.ptr; assert(GC.addrOf(p) !is null); writeln("Free heap"); __delete(i); assert(GC.addrOf(p) is null); } ```
Jul 17 2023
This works also, ``` class C { int * pa; int [] a; // Constructor this() {writefln("Called constructor"); pa=cast(int *)malloc(1000*int.sizeof); a=pa[0..1000]; } } void dofun() { scope x=new C; x.a[3]=5; writefln("%12x",&x); } int main(){ dofun(); dofun(); return 0; } ```
Jul 17 2023
On Monday, 17 July 2023 at 16:52:00 UTC, Alain De Vos wrote:This works also, ``` class C { int * pa; int [] a; // Constructor this() {writefln("Called constructor"); pa=cast(int *)malloc(1000*int.sizeof); a=pa[0..1000]; } } void dofun() { scope x=new C; x.a[3]=5; writefln("%12x",&x); } int main(){ dofun(); dofun(); return 0; } ```Remember to use free, this is not managed by the GC
Jul 17 2023