none
Problem with Garbage Collection, unmanged dll and D.E.P. RRS feed

  • Question

  • i'm using an unmanaged graphics engine dll. my wrapper code works. in that i can create a small spinning cube console application. however when i close my program D.E.P. crashes the program. i have managed to find out the cause of this. is due to the GC freeing the OpenGL buffer before it unloads the unmanaged graphics engine dll. currently i'm using this rather poor yet working method to avoid the D.E.P. crash.


    public static void Terminate()
    {
        GC.Collect();
        Engine.EndRender();
        GC.Collect();
        System.Diagnostics.Process.GetCurrentProcess().Kill();
    }

    i simply call Terminate() at the end of my code to exit program. i would like to know if there is a better/cleaner way. to get the GC to unload the dll before it frees the OpenGL buffer. so as to avoid the D.E.P. crash.
    Saturday, May 31, 2008 4:18 AM

All replies

  • Hi enabblerbr,

    Since you use some unmanaged resource in the .Net code, I believe you can try to implement a dispose method in the unmanaged class, and calling the dispose method to release the resource when you do not use it anymore.

    In addition to the dispose method implementation, refer to the Implementing a Dispose Method.

    Regards,

    Xun


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Marked as answer by enablerbr Wednesday, June 4, 2008 12:24 PM
    • Unmarked as answer by nobugzModerator Saturday, June 7, 2008 3:18 PM
    Wednesday, June 4, 2008 3:38 AM
  • i had thought about dipose but i'm not sure how i would go about it with my code.

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Runtime.InteropServices;  
    using System.Text;  
     
    namespace TestDllCode  
    {  
        public static class Engine  
        {  
            [DllImport("engine.dll", EntryPoint = "Graphics"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern int TGraphics(int width, int height, int depth, int hertz, int flags);  
            public static int Graphics(int width, int height, int depth, int hertz, int flags)  
            {  
                return TGraphics(width, height, depth, hertz, flags);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "EndRender"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TEndRender();  
            public static void EndRender()  
            {  
                TEndRender();  
            }  
     
            [DllImport("engine.dll", EntryPoint = "CreateWorld"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern int TCreateWorld();  
            public static int CreateWorld()  
            {  
                return TCreateWorld();  
            }  
     
            [DllImport("engine.dll", EntryPoint = "RenderWorld"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TRenderWorld();  
            public static void RenderWorld()  
            {  
                TRenderWorld();  
            }  
            [DllImport("engine.dll", EntryPoint = "ClearWorld"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TClearWorld();  
            public static void ClearWorld()  
            {  
                TClearWorld();  
            }  
            [DllImport("engine.dll", EntryPoint = "CreateCamera"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern int TCreateCamera(int parent);  
            public static int CreateCamera(int parent)  
            {  
                return TCreateCamera(parent);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "CreatePointLight"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern int TCreatePointLight(float range, int parent);  
            public static int CreatePointLight(float range, int parent)  
            {  
                return TCreatePointLight(range, parent);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "CreateCube"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern int TCreateCube(int parent);  
            public static int CreateCube(int parent)  
            {  
                return TCreateCube(parent);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "MoveEntity"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TMoveEntity(int entity, float[] direction);  
            public static void MoveEntity(int entity, float[] direction)  
            {  
                TMoveEntity(entity, direction);  
            }  
            public static void MoveEntity(int entity, Vector3D direction)  
            {  
                TMoveEntity(entity, direction.ToFloatArray());  
            }  
     
            [DllImport("engine.dll", EntryPoint = "TurnEntity"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TTurnEntity(int entity, float[] angle, int global);  
            public static void TurnEntity(int entity, float[] angle, int global)  
            {  
                TTurnEntity(entity, angle, global);  
            }  
            public static void TurnEntity(int entity, Vector3D angle, int global)  
            {  
                TTurnEntity(entity, angle.ToFloatArray(), global);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "KeyHit"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern int TKeyHit(int key);  
            public static int KeyHit(int key)  
            {  
                return TKeyHit(key);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "DrawText"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TDrawText(string text, int x, int y);  
            public static void DrawText(string text, int x, int y)  
            {  
                TDrawText(text, x, y);  
            }  
     
            [DllImport("engine.dll", EntryPoint = "Flip"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TFlip(int sync);  
            public static void Flip(int sync)  
            {  
                TFlip(sync);  
            }  
            [DllImport("engine.dll", EntryPoint = "AppTerminate"CallingConventionCallingConvention = CallingConvention.StdCall)]  
            private static extern void TAppTerminate();  
            public static void AppTerminate()  
            {  
                TAppTerminate();  
            }  
     
            public static void Terminate()  
            {  
                Engine.EndRender();  
            }  
     
            public struct Vector3D  
            {  
                public float x;  
                public float y;  
                public float z;  
     
                public Vector3D(float newx, float newy, float newz)  
                {  
                    x = newx;  
                    y = newy;  
                    z = newz;  
                }  
     
                public float[] ToFloatArray()  
                {  
                    float[] p = new float[3];  
                    p[0] = x;  
                    p[1] = y;  
                    p[2] = z;  
                    return p;  
                }  
     
                public float Magnitude()  
                {  
                    return (float)System.Math.Sqrt((x * x) + (y * y) + (z * z));  
                }  
     
                public void Normalize()  
                {  
                    float m = Magnitude();  
                    x /= m;  
                    y /= m;  
                    z /= m;  
                }  
     
                public Vector3D Flip()  
                {  
                    return new Vector3D(-x, -y, -z);  
                }  
     
                public Vector3D Copy()  
                {  
                    return new Vector3D(x, y, z);  
                }  
     
                public static float Dot(Vector3D value1, Vector3D value2)  
                {  
                    return (value1.x * value2.x + value1.y * value2.y + value1.z * value2.z);  
                }  
     
                public static Vector3D operator +(Vector3D value1, Vector3D value2)  
                {  
                    return new Vector3D(value1.x + value2.x, value1.y + value2.y, value1.z + value2.z);  
                }  
     
                public static Vector3D operator *(Vector3D value1, float scalar)  
                {  
                    return new Vector3D(value1.x * scalar, value1.y * scalar, value1.z * scalar);  
                }  
     
                public static Vector3D operator *(float scalar, Vector3D value1)  
                {  
                    return new Vector3D(value1.x * scalar, value1.y * scalar, value1.z * scalar);  
                }  
     
                public static bool operator ==(Vector3D value1, Vector3D value2)  
                {  
                    if (value1.x == value2.x & value1.y == value2.y & value1.z == value2.z)  
                    {  
                        return true;  
                    }  
                    return false;  
                }  
     
                public static bool operator !=(Vector3D value1, Vector3D value2)  
                {  
                    if (value1.x != value2.x | value1.y != value2.y | value1.z != value2.z)  
                    {  
                        return true;  
                    }  
                    return false;  
                }  
     
                public override bool Equals(object obj)  
                {  
                    return base.Equals(obj);  
                }  
     
                public override int GetHashCode()  
                {  
                    return base.GetHashCode();  
                }  
            }  
        }  
    Wednesday, June 4, 2008 12:23 PM
  • Is your question answered?  It is marked as answered but you don't sound like it was.  Who marked it?
    Hans Passant.
    Thursday, June 5, 2008 11:48 PM
    Moderator
  • i 've marked it by accident. as  i still have no real idea if that is the way to solve my problem.
    Friday, June 6, 2008 12:20 AM
  • You can P/Invoke LoadLibrary() at the start of your program, before you P/Invoke any of the engine.dll exports.  Then call FreeLibrary() twice at the end to force the DLL to unload.  Not so sure it will work, you'd assume the engine is dead when you call EndRender()
    Hans Passant.
    Friday, June 6, 2008 1:54 AM
    Moderator
  •  i want to make my wrapper a dll. so will the loadlibrary/freelibrary still work? how do i code this loadlibrary/freelibrary?
    Saturday, June 7, 2008 1:57 PM
  • You would use Load/FreeLibrary() on engine.dll, not your assembly.  Visit pinvoke.net for the required [DllImport] declaration.
    Hans Passant.
    Saturday, June 7, 2008 3:18 PM
    Moderator
  • seems even LoadLibrary(),FreeLibrary() doesn't solve the problem.
    Sunday, June 8, 2008 5:10 PM
  • So, are you calling FreeLibrary() twice?
    Hans Passant.
    Sunday, June 8, 2008 6:02 PM
    Moderator
  • like this.

    FreeLibrary(pDll);
    EndRender();
    FreeLibrary(pDll);

    i'm wondering if its because the engine.dll itself uses two unmanaged dlls.


    the error message i get when run it on windows xp pro computer instead of my vista home premium 64bit without the freelibrary code is.

    The instruction at "0x03cb3c40" referenced memory at "0x03cb3c40". The memory could not be "read". Click on OK to terminate the program.



    is there any tool i can use to get a better understanding of what exactly has gone wrong with my code?

    • Edited by enablerbr Sunday, June 8, 2008 7:06 PM added text
    Sunday, June 8, 2008 6:50 PM
  • In addition to "LoadLibrary" and "FreeLibrary", consider using "GetProcAddress" and "Marshal.GetDelegateForFunctionPointer". Good luck!
    Tuesday, June 10, 2008 4:29 PM