www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to free memory ater use of "new" to allocate it.

reply Alain De Vos <devosalain ymail.com> writes:
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
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
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
parent reply Alain De Vos <devosalain ymail.com> writes:
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
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
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
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
next sibling parent reply Alain De Vos <devosalain ymail.com> writes:
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
next sibling parent reply Alain De Vos <devosalain ymail.com> writes:
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
parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
prev sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
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
parent reply Alain De Vos <devosalain ymail.com> writes:
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
parent reply drug007 <drug2004 bk.ru> writes:
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
next sibling parent reply Alain De Vos <devosalain ymail.com> writes:
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
parent drug007 <drug2004 bk.ru> writes:
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
prev sibling parent Alain De Vos <devosalain ymail.com> writes:
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
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
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
parent reply Alain De Vos <devosalain ymail.com> writes:
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
parent Ernesto Castellotti <erny.castell gmail.com> writes:
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