Memory leak while calling .net method

Hello everyone,

I got memory leak issue when I call .net method from clarion application. I have used libmaker to convert .net DLL to lib file and used in clarion project. I am passing BSTRING parameters to the .net method and receives BSTRING result in reference variable. Check the below code

Clarion side:

MAP
    MODULE('NetApp')  
      ApiValidate (BSTRING pData, BSTRING pSoftwareKey, *BSTRING pResult), LONG, PASCAL, NAME('Validate')
    END
  END   

ApiClass.Run        Procedure()
lcData BSTRING
sKey  BSTRING
result  BSTRING
retval long

CODE

lcData= GETREG(REG_LOCAL_MACHINE, RegKey ,'Data')   //retrieve some data from registry
sKey  =’test data’
retval= ApiValidate (lcData, sKey , result)
clear(lcData)
clear(sKey)
clear(result)

.Net side

namespace MLNetToolbox
{
    public enum MLError
    {      
        ML_OK = 0
    }
    public sealed class WinAPI
    {

      [DllExport("Validate", CallingConvention = CallingConvention.StdCall)]
    public static MLError Validate ([MarshalAs(UnmanagedType.BStr)] string data,     [MarshalAs(UnmanagedType.BStr)] string softwareKey, [MarshalAs(UnmanagedType.BStr)] out string result)
   {
     result =”test”;               
     return MLError.ML_OK;
   }
 }
}

We are creating web application where on each request the application will call the above clarion method. While running the performance test, we have noticed significant increase in memory consumption. It shoots up to 500 mb. I used .Net framework 4.8 to build .net dll. Couldn’t figure out the potential cause of memory leak. It would be great if someone can help me on this.

It goes upto 500mb, does it keep going up beyond that?

Sorry Bruce I forgot to mention one thing. Actually the method which I mentioned in the post consumes around 274 MB. But if I call other .Net methods then certainly it can go beyond 500 MB

Sys Internals VMMap can help see memory use and track leaks. Are you saying after 1 call your memory goes up 274 MB or is it many calls.

I’m no .net expert, but don’t StdCall and Pascal have different porpoises?

1 Like

OIC, there’s no pascal in .net. (blush)

No Carl. After running around 2365 times memory goes upto 274 MB. Its like sending 2365 simultaneous request. I will look into VMMap

Yes. There is difference in the calling convention. Not sure whether that could be the reason for the leak. Need to investigate more on this

You’ll want to change your .Net to CallingConvention = CallingConvention.Pascal since Clarion is prototyped as PASCAL.

It seems like your code would not work because the parameters are in a different order i.e. Pascal pushed Left to Right versus Right to Left for StdCall.

There’s this .Net DllExport tool that defaults to the Cdecl Convention which Clarion can specific “C”

I just got confused with explanation of pascal attribute in clarion help. There it says “In 32-bit programs, both C and PASCAL conventions pass the parameters to the stack from right to left.”

I have changed the calling convention in both .net and clarion. But leak didn’t disappear

Perhaps your problem has to do with the memory leak in C11.1?

See:
https://clarionhub.com/t/alternative-debug-rtl-that-checks-the-heap-for-memory-leaks/6287

Best regards
Jeffrey

May be..But I couldn’t access the link which you shared

Hmm, that’s weird. I have attached a pdf of the conversation here:

Thanks Jkuit..I will check

Might be. Because I am using Clarion 11.1.13815

You might try passing all 3 BSTRING by address as *BSTRING

Passing by Value the RTL would have to duplicate them and maybe it’s not disposing. It also will be faster.

AFAIK BString support in Clarion is not complete. Like you cannot put them in a Group or Queue it will crash or leak. It might not really be passing them by value.

If you have the time, you can try to rewrite the Clarion/.NET parameters exchange using HeapAlloc/HeapFree.

For example, to return a string, the .NET side allocates heap memory, sets its value as an ANSI C string, and returns the heap address.

The Clarion side can read the string using st.SetValueByCstringAddress(addr) and then release the memory with HeapFree(GetProcessHeap(),0,addr). Of course, it will be better to write a front-end class.

I did this recently and it worked great. I used Claude Code to write the .NET side. I asked it to create a native AOT 32-bit DLL (requires .NET 9) to be called from C programs.

Eh? Where does it say Pascal and C parameter passing are the same?