Like Tree1Likes
  • 1 Post By Mario F.

Unmanaged Heap Memory Leak

This is a discussion on Unmanaged Heap Memory Leak within the C# Programming forums, part of the General Programming Boards category; I am developing a video conferencing system (see my other thread ), and I am having some trouble with memory ...

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    2,456

    Unmanaged Heap Memory Leak

    I am developing a video conferencing system (see my other thread), and I am having some trouble with memory leaks in the unmanaged heap. I think it's related to directshow, but the tools I've tried (ANTS and the SciTech memory profiler) do nothing to help find problems in the unmanaged heap. I'm doing everything I can to free memory that's being allocated, but I'm obviously missing something.

    I'm looking for other suggestions of tools to use to try to find the leak.

  2. #2
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    First thing I'd do is call GC.Collect() to see if the memory is recovered or if it is still tied up somewhere. That would give me some idea of how to proceed.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    2,456
    I'm doing that at various locations in the program, but to no avail. memory usage on the unmanaged heap just keeps climbing out of control. I am freeing the buffers allocated for DirectShow, but it's either not freeing them, or it's allocating other buffers over which I have no control.

  4. #4
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,487
    Also, if this has anything to do with the DirectShow.net library, are you using the debug version of the assembly?
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    2,456
    Quote Originally Posted by Mario F. View Post
    Also, if this has anything to do with the DirectShow.net library, are you using the debug version of the assembly?
    I rebuilt the assembly in release mode, as well as my program, just to be sure, and it made no difference.

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,487
    I didn't ask because of that. But I can see that you had the debug version of the assembly. So that's fine.

    You can be almost sure the leak is on this library if you aren't doing any other kind of access to unmanaged code. But it can still be provoked by your own code if you are accessing these resources the wrong way (you mentioned before lack of proper documentation for this library and that may be a problem here).

    What I suggest you do for now to at least point at the source of the leak, is to make selective commenting of your source code that accesses unmanaged code (directly or indirectly through directshow.net) while checking perfmon until you get a flat line for unmanaged memory usage. Here's how:

    1. Run you app and start perfmon
    2. Add two new counters to perfom
    2.1. From the section ".Net CLR Memory", select "#bytes in all Heaps" and associate it with your process
    2.2. From the section "Process", select "#private bytes" and associate it with your process

    Start commenting any relevant sections of your code and rerun it. You want a flat line for "#private bytes". Once you get that, you located the source of the leak. Or at least the managed code that controls the source of the leak.

    EDIT: You may have to scale the "#private bytes" line a bit. If it's set at the top of the graph, doubleclick that marker in the listbox at the bottom of perfmon, and under the "Data" tab decrease the scale by moving up on the dropdown box that you get from the "Scale" button. This will allow you to set that line closer to your managed heap line and in full view.

    Now, once you locate the leak, you are not off the hook. Post the code here if you can't see anything wrong with your managed code. If we can't either, chances are the leak is located within DirectShow.Net. But at least you'll know the resource you are using from it that is causing the leak.
    Last edited by Mario F.; 03-28-2011 at 07:00 PM.
    itsme86 likes this.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    Leaks in the unmanaged heap are simple to fix and find through standard C++ leak checks and leak detection methods. Leaks in the managed heap is where the fun begins and some of those are very hard to track down and/or actually determine if they are a leak or just a result of a very lazy GC. Most of the tools mentioned in this thread are for finding managed heap leaks.

    The only way you can really leak DirectShow objects is improper COM object cleanup and detecting COM leaks is a completely different process than detecting managed/unmanaged heap leaks. If you call CoCreateInstance or CoCreateInstanceEx you also must then call Release on the interface pointers you get back from those method calls. If you do not do this you will leak DirectShow. COM leaks also compound themselves b/c normally COM is like having a toolbox full of drawers and tools in them. One drawer may contain several tools and/or other drawers. If you leak the parent object then you will also leak all of the objects it manages or that spawned via its various interface calls. Direct3D also has this same type of structure. If you leak a texture or two or a vertex buffer then the entire device will most likely leak which will cause hundreds of leaks b/c the device could not clean up or was in a bad state to do so. Also keep in mind that some COM methods increase the ref count on the object and if you do not call release on it then your final release will leave the ref count at 1 and the object will not clean up.

    There are COM based tools to detect these leaks. Direct3D leaks can be found via the dxcpl and by checking break on memory leaks and entering the allocation number you get back in from Direct3D into the edit box. This information will only be returned if you define D3D_DEBUG_INFO. I'm sure there is a similar approach to DirectShow and since DirectShow used to be a part of DirectX you may still be able to use the DirectX control panel method for detecting leaks but I cannot verify that since I do not work that heavily with DirectShow.
    Last edited by VirtualAce; 03-29-2011 at 01:12 AM.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    2,456
    I've actually used ANTS to determine that in fact I do have an unmanaged memory leak.

    My code is based on the DxSnap sample included with the samples for DirectShow.Net, and uses the Capture class from that sample.

    Code:
    // allocate an array of bytes into which we will copy the image buffer from Click()
    byte[] imgBuffer = new byte[Math.Abs(cam.Stride) * cam.Height];
    
    // cam is a Capture object
    IntPtr imgPtr = cam.Click();
    
    // copy the buffer
    Marshal.Copy(imgPtr, imgBuffer, 0, imgBuffer.Length);
    
    // free the buffer from Click()
    Marshal.FreeCoTaskMem(imgPtr);
    
    // get a pinned array handle to the byte array
    var pinnedArray = GCHandle.Alloc(imgBuffer, GCHandleType.Pinned);
    
    // get the pointer to the array
    var arrayPtr = pinnedArray.AddrOfPinnedObject();
    
    // create the new bitmap
    Bitmap bMap = new Bitmap(cam.Width, cam.Height, cam.Stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, arrayPtr);
    
    // free the pinned array handle
    pinnedArray.Free();
    I don't think I'm doing anything wrong, but I'm not very experienced with COM and DirectX, especially in the .Net framework.

  10. #10
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,487
    I'm confused at a part of that code, but that may be because of my only partial knowledge in mixing managed and unmanaged memory. Not something that I had to so far, except once. But here it goes, anyways:

    Why not?
    Code:
    GCHandle imgch = GCHandle.Alloc(imgBuffer);
    
    // create the new bitmap
    Bitmap bMap = new Bitmap(cam.Width, cam.Height, cam.Stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, GCHandle.ToIntPtr(imgch));
    
    // free the handle
    imgch.Free();
    Anyways, I don't think the above -- if valid -- will have any effect. It's actually more of a question than a suggestion. Here's however a couple of thoughts:

    - How does the Click() method initialize the intPtr? Check if it is with AllocCoTaskMem.
    - If the above is true and this code represents the only two situations where allocation e deallocation of unmanaged memory are present, then the leak is not on that piece of code -- or is, but at the library level.

    Check Virtual Ace's post for hints on finding tools to debug COM. You may wish to also email the library author. If that's all your code is doing, they will want to know there's a possible leak in Click() -- being that my personal bet.

    EDIT: Oh and one final note: Only use implicitly typed variables on those instances where they are needed (or convenient). It's poor form to use them this liberally. I understand you probably just copy-pasted and made the necessary changes, but there's no excuse to use them as it is shown in your code.
    Last edited by Mario F.; 03-29-2011 at 05:29 PM.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  11. #11
    Registered User
    Join Date
    Oct 2006
    Posts
    2,456
    Quote Originally Posted by Mario F. View Post
    - How does the Click() method initialize the intPtr? Check if it is with AllocCoTaskMem.
    yes it is, and you'll note that I free the memory from Click() in my own code.

    - If the above is true and this code represents the only two situations where allocation e deallocation of unmanaged memory are present, then the leak is not on that piece of code -- or is, but at the library level.
    I have the source to the DirectShowNet library, but I doubt that the leak is in there, because their example program, which uses code very much like mine, does not leak.

    Check Virtual Ace's post for hints on finding tools to debug COM. You may wish to also email the library author. If that's all your code is doing, they will want to know there's a possible leak in Click() -- being that my personal bet.
    I have the source for the Click() method, and there doesn't appear to be anything amiss there.

    I'm beginning to think that it may be related to the fact that I'm trying to do this in a WPF application, when the code I'm basing it on was designed to work with windows forms. I still don't understand where my memory is getting leaked though, because I'm freeing all unmanaged memory that is being allocated, as far as I know.

    EDIT: Oh and one final note: Only use implicitly typed variables on those instances where they are needed (or convenient). It's poor form to use them this liberally. I understand you probably just copy-pasted and made the necessary changes, but there's no excuse to use them as it is shown in your code.
    honestly, criticizing me for a piece of code (that is completely valid code) that uses two instances of the "var" keyword contributes nothing to a solution to my problem. I appreciate the help you've offered so far, but please try to keep to the subject at hand instead of trying to "teach" me how to write better code.

  12. #12
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,487
    Quote Originally Posted by Elkvis View Post
    Honestly, criticizing me for a piece of code (that is completely valid code) that uses two instances of the "var" keyword contributes nothing to a solution to my problem. I appreciate the help you've offered so far, but please try to keep to the subject at hand instead of trying to "teach" me how to write better code.
    Yes. Well, good luck.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with custom dynamic memory allocation routines
    By BLauritson in forum C++ Programming
    Replies: 12
    Last Post: 03-11-2010, 06:26 AM
  2. memory leak
    By rahulsk1947 in forum C Programming
    Replies: 2
    Last Post: 11-11-2007, 12:27 PM
  3. Memory leak with detached pthreads - how to free?
    By rfk in forum Linux Programming
    Replies: 2
    Last Post: 08-17-2007, 06:50 AM
  4. Pointer's
    By xlordt in forum C Programming
    Replies: 13
    Last Post: 10-14-2003, 02:15 PM
  5. heap question
    By mackol in forum C Programming
    Replies: 1
    Last Post: 11-30-2002, 04:03 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21