www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Memory leak issue between extern (c) and D function

reply backtrack <me alchemy.in> writes:
Dear All, I am new to D lang. I have been given a task to consume 
the .dll generated from a D lang project.

I added extern (c) function for call the .dll from CPP file. i 
have code like below


```
// myfile.d
extern(c)
{

     mystruct* getmystruct()
     {
         mystruct* mystruct =  
cast(mystruct*)malloc(mystruct.sizeof);
         return mystruct;

     }

    char* do_some_work(const mystruct* mystruct , immutable(char)* 
  input, int inputlenght)
    {

        InputStruct input;
        input.name = input[0..inputlenght];
        auto output = mystruct.getValue(input);
        // do some process and return char*
        return output_char.ptr;
     }

}


struct mystruct
{
    OutputStruct[] getValue(InputStruct input)
   {
     // some string operation and other operation done here
     return output
   }
}

struct InputStruct
{
    string name;
}

struct OutputStruct
{
    string name;
    string value;
}

```

Now i have my cpp file which calls like below

```
mystruct* mystruct = lib.getmystruct();
char* output = lib.do_some_work(mystruct, "input", 5);

```

The problem i am facing is, the memory keep on increasing and i 
am not able to fix the memory issue. I am suspecting that since 
the D lang function is called from extern(c) function GC is not 
clearing the memeory.

Can you please help me on this?

Thank you
Apr 13 2023
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 14 April 2023 at 03:50:37 UTC, backtrack wrote:
 Dear All, I am new to D lang. I have been given a task to 
 consume the .dll generated from a D lang project.

 I added extern (c) function for call the .dll from CPP file. i 
 have code like below


 ```
 // myfile.d
 extern(c)
 {

     mystruct* getmystruct()
     {
         mystruct* mystruct =  
 cast(mystruct*)malloc(mystruct.sizeof);
         return mystruct;

     }
 ```
[...]
 Now i have my cpp file which calls like below

 ```
 mystruct* mystruct = lib.getmystruct();
 char* output = lib.do_some_work(mystruct, "input", 5);

 ```

 The problem i am facing is, the memory keep on increasing and i 
 am not able to fix the memory issue. I am suspecting that since 
 the D lang function is called from extern(c) function GC is not 
 clearing the memeory.
The GC does not clean up memory allocated by `malloc`. Since you're using `malloc` to allocate your memory, the only way you can free it is by using `free`. If you want the GC to clean up your memory, use `new` to allocate it instead of `malloc`. Like this: ```d mystruct* getmystruct() { return new mystruct; } ```
Apr 13 2023
parent reply Guillaume Piolat <first.last spam.org> writes:
On Friday, 14 April 2023 at 04:43:39 UTC, Paul Backus wrote:
 If you want the GC to clean up your memory, use `new` to 
 allocate it instead of `malloc`. Like this:

 ```d
 mystruct* getmystruct()
 {
     return new mystruct;
 }
 ```
That won't work because the C++ programm calling the D dynlib will not have its stack scanned, leading to that object being reclaimed early. OP could add another extern(C) D function to free the allocated object. Or another extern(C) D function to call GC.addRoot
Apr 14 2023
next sibling parent Guillaume Piolat <first.last spam.org> writes:
On Friday, 14 April 2023 at 11:15:59 UTC, Guillaume Piolat wrote:
 OP could add another extern(C) D function to free the allocated 
 object.
 Or another extern(C) D function to call GC.addRoot
Or simpler, add that object to a list of object in D DLL __gshared list, then clear the list (or set individual reference to null) if you want to reclaim space.
Apr 14 2023
prev sibling parent reply backtrack <me alchemy.in> writes:
On Friday, 14 April 2023 at 11:15:59 UTC, Guillaume Piolat wrote:
 On Friday, 14 April 2023 at 04:43:39 UTC, Paul Backus wrote:
 If you want the GC to clean up your memory, use `new` to 
 allocate it instead of `malloc`. Like this:

 ```d
 mystruct* getmystruct()
 {
     return new mystruct;
 }
 ```
That won't work because the C++ programm calling the D dynlib will not have its stack scanned, leading to that object being reclaimed early. OP could add another extern(C) D function to free the allocated object. Or another extern(C) D function to call GC.addRoot
Thank you for your response. I added something like this in extern (c) function. ``` __delete(output); ``` When i debugged, it shows null to output after executing above line. however the memory is not releasing. Thank you.
Apr 14 2023
parent Guillaume Piolat <first.last spam.org> writes:
On Friday, 14 April 2023 at 17:31:02 UTC, backtrack wrote:
 however the memory is not releasing.
With the D GC, your object can have three state: - reachable by GC. If D code can see the reference, then it's "alive", kept alive by GC scanning. The GC finds the reference and doesn't touch it. This is the invariant that you need to maintain when interacting with C. - unreachable by GC and thus at a risk of being reclaimable at next GC collect. This happens when all your references are null. If you want immediate destructor, call .destroy() before nulling your references so that the object can't be scanned. By calling destroy() on all your objects manually, you can reach destruction determinism. - non-existing, memory has been reclaimed. You don't necessarily need to do that with __delete, this should be very rare even. If the references to the object are null, then their destructor will eventually be called if it wasn't already with .destroy, the memory eventually reclaimed. Usually you don't need to care about that state.
Apr 16 2023
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 4/13/23 20:50, backtrack wrote:

      mystruct* getmystruct()
      {
          mystruct* mystruct = cast(mystruct*)malloc(mystruct.sizeof);
          return mystruct;

      }
There must be a corresponding function to do the cleaning: void freemystruct(mystruct* ptr) { free ptr; } You have to make sure on the D side that freemystruct() is called once for each getmystruct(). I have the following presentation that covers similar concepts: https://www.youtube.com/watch?v=FNL-CPX4EuM I think this point is most relevant: https://www.youtube.com/watch?v=FNL-CPX4EuM&t=1833s Ali
Apr 15 2023