Thread: memory management when linking to a C DLL

  1. #1
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268

    memory management when linking to a C DLL

    I'm hoping I can find someone here that can answer this:

    Let's say I have a DLL written in C which has the following functions:

    Code:
    void get_string(char **pszStr)
    {
       char *s = malloc(32);
       strcpy(s,"Hello there");
       *pszStr = s;
    }
    
    void free_string(char *pszStr)
    {
       free(pszStr);
    }
    Now when I call this function using C#:
    Code:
    [DllImport("cdll.dll")]
    unsafe static extern void get_string(out string str);
    [DllImport("cdll.dll")]
    unsafe static extern void free_string(string str);
    
    public void someMethod()
    {
       string str;
       get_string(out str);
       free_string(str);  // <- is this necessary?
    }
    Is it necessary to call free_string() here? In C# memory management of the string class is taken care of by the implementation, but in the C dll the memory must be explicity released. I'm a little worried that free_string() won't actually work on the C# string, and therefore this is actually leaking memory.

  2. #2
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Each time a variable is passed between managed and unmanaged code it is marshalled. AFAIK, for strings, a copy is passed, therefore the pointer to the string you are freeing will probably not be the one you allocated.

    If it were my code, I'd try to keep all the memory management in C# (if at all possible).

    The StringBuilder class has a different treatment under marchalling than a string in that it can be passed to unmanaged code, changed, and then returned.

    Here's my ammended dll
    Code:
    #include <cstring>
    #include <windows.h>
    #define CSHARP_DLL_API extern "C" __declspec(dllexport) 
    
    BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
    {
        return TRUE;
    }
    
    CSHARP_DLL_API void get_stringsafe(char *pszStr)
    {
       strcpy(pszStr,"Hello there");
    }
    And here's my C# code
    Code:
    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    
    public class MyDLL
    {
        [DllImport("TestCSharp.dll")]
        public static extern void get_stringsafe(StringBuilder pszStr);
    }
    
    class MyMain
    {
        public static void Main()
        {
            StringBuilder oString = new StringBuilder();
            oString.Capacity = 50;
            MyDLL.get_stringsafe(oString);
            Console.WriteLine(oString);    
        }
    }

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Hey fordy,

    From what you said, it sounds like the code the way I have it is indeed a memory leak. The data will get copied to my string, but then I lose the pointer that I need to free the memory.

    I really wanted to avoid changing the DLL code (it is a massive third party DLL), so I'll probably write a wrapper DLL in C that is friendlier to C#.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. tools for finding memory leaks
    By stanlvw in forum C++ Programming
    Replies: 4
    Last Post: 04-03-2009, 11:41 AM
  2. Memory management - How/why/when
    By micke_b in forum C Programming
    Replies: 29
    Last Post: 11-07-2007, 12:26 PM
  3. Replies: 4
    Last Post: 07-06-2006, 02:53 AM
  4. Memory Management
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 06-01-2003, 09:01 PM
  5. Replies: 4
    Last Post: 10-11-2002, 06:58 AM