diff --git a/bindings/dotnet/Unicorn/Unicorn.fs b/bindings/dotnet/Unicorn/Unicorn.fs
index 79108c1d..5c881e57 100644
--- a/bindings/dotnet/Unicorn/Unicorn.fs
+++ b/bindings/dotnet/Unicorn/Unicorn.fs
@@ -51,6 +51,7 @@ and Unicorn(arch: Int32, mode: Int32) =
     let _inHooks = new Dictionary<IntPtr, (InHook * Object)>()
     let _outHooks = new Dictionary<IntPtr, (OutHook * Object)>()
     let _syscallHooks = new Dictionary<IntPtr, (SyscallHook * Object)>()
+    let _disposablePointers = new List<nativeint>()
 
     let mutable _eng = [|UIntPtr.Zero|]
 
@@ -66,10 +67,14 @@ and Unicorn(arch: Int32, mode: Int32) =
         callbacks.Keys
         |> Seq.tryFind(fun k -> match callbacks.[k] with | (c, _) -> c = callback)
         |> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore)
+
+    let allocate(size: Int32) =
+        let mem = Marshal.AllocHGlobal(size)
+        _disposablePointers.Add(mem)
+        mem.ToPointer()
             
-    do
-        let mem = Marshal.AllocHGlobal(IntPtr.Size)
-        _eng <- [|new UIntPtr(mem.ToPointer())|]
+    do  
+        _eng <- [|new UIntPtr(allocate(IntPtr.Size))|]
         let err = NativeUnicornEngine.uc_open(uint32 arch, uint32 mode, _eng)
         checkResult(err, "Unable to open the Unicorn Engine")
 
@@ -130,8 +135,8 @@ and Unicorn(arch: Int32, mode: Int32) =
         let id = getId()
         _codeHooks.Add(id, (callback, userData))
 
-        let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))        
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -147,7 +152,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _blockHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -163,7 +168,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _interruptHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_noarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), id) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -179,7 +184,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _memReadHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -195,7 +200,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _memWriteHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -212,7 +217,7 @@ and Unicorn(arch: Int32, mode: Int32) =
             _memEventHooks.Add(id, (callback, userData))
 
             let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline))
-            let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+            let hh = new UIntPtr(allocate(IntPtr.Size))
             match NativeUnicornEngine.hook_add_noarg(_eng.[0], hh, check, new UIntPtr(funcPointer.ToPointer()), id) |> this.CheckResult with 
             | Some e -> raise e | None -> ()
 
@@ -241,7 +246,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _inHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_IN)) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -254,7 +259,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _outHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_OUT)) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
 
@@ -267,7 +272,7 @@ and Unicorn(arch: Int32, mode: Int32) =
         _syscallHooks.Add(id, (callback, userData))
 
         let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline))
-        let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
+        let hh = new UIntPtr(allocate(IntPtr.Size))
         match NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_SYSCALL)) |> this.CheckResult with 
         | Some e -> raise e | None -> ()
     
@@ -275,3 +280,24 @@ and Unicorn(arch: Int32, mode: Int32) =
         let (major, minor) = (new UIntPtr(), new UIntPtr())
         let combined = NativeUnicornEngine.version(major, minor)
         (major.ToUInt32(), minor.ToUInt32(), combined)
+
+    abstract Dispose : Boolean -> unit
+    default this.Dispose(disposing: Boolean) =
+        if (disposing) then
+            // free managed resources, this is the default dispose implementation pattern
+            ()
+
+        _disposablePointers
+        |> Seq.filter(fun pointer -> pointer <> IntPtr.Zero)
+        |> Seq.iter Marshal.FreeHGlobal
+
+    member this.Dispose() =
+        this.Dispose(true)
+        GC.SuppressFinalize(this)
+
+    override this.Finalize() =
+        this.Dispose(false)
+
+    interface IDisposable with
+        member this.Dispose() =
+            this.Dispose()
diff --git a/bindings/dotnet/Unicorn/Unicorn.fsproj b/bindings/dotnet/Unicorn/Unicorn.fsproj
index 8f6ee136..1bb52e8c 100644
--- a/bindings/dotnet/Unicorn/Unicorn.fsproj
+++ b/bindings/dotnet/Unicorn/Unicorn.fsproj
@@ -8,9 +8,9 @@
     <ProjectGuid>6f0e55fa-a056-45ff-bb24-641457b430a8</ProjectGuid>
     <OutputType>Library</OutputType>
     <RootNamespace>UnicornSln</RootNamespace>
-    <AssemblyName>UnicornSln</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <TargetFSharpCoreVersion>4.3.0.0</TargetFSharpCoreVersion>
+    <AssemblyName>UnicornManaged</AssemblyName>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+    <TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>
     <Name>Unicorn</Name>
     <TargetFrameworkProfile />
   </PropertyGroup>
@@ -22,8 +22,11 @@
     <OutputPath>bin\Debug\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <WarningLevel>3</WarningLevel>
-    <DocumentationFile>bin\Debug\UnicornSln.XML</DocumentationFile>
+    <DocumentationFile>bin\Debug\UnicornManaged.XML</DocumentationFile>
     <PlatformTarget>x86</PlatformTarget>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <WarningsAsErrors />
+    <EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
diff --git a/bindings/dotnet/UnicornTests/App.config b/bindings/dotnet/UnicornTests/App.config
index 9c05822f..2d2a12d8 100644
--- a/bindings/dotnet/UnicornTests/App.config
+++ b/bindings/dotnet/UnicornTests/App.config
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8" ?>
+<?xml version="1.0" encoding="utf-8"?>
 <configuration>
     <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
     </startup>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/bindings/dotnet/UnicornTests/Program.cs b/bindings/dotnet/UnicornTests/Program.cs
index dde8d1e8..9cdd5cd2 100644
--- a/bindings/dotnet/UnicornTests/Program.cs
+++ b/bindings/dotnet/UnicornTests/Program.cs
@@ -34,6 +34,9 @@ namespace UnicornTests
             // Run all shellcode tests
             ShellcodeTest.TestX86Code32Self();
             ShellcodeTest.TestX86Code32();
+
+            Console.Write("Tests completed");
+            Console.ReadLine();
         }
     }
 }
diff --git a/bindings/dotnet/UnicornTests/ShellcodeTest.cs b/bindings/dotnet/UnicornTests/ShellcodeTest.cs
index e254fb4a..af1481f3 100644
--- a/bindings/dotnet/UnicornTests/ShellcodeTest.cs
+++ b/bindings/dotnet/UnicornTests/ShellcodeTest.cs
@@ -72,33 +72,35 @@ namespace UnicornTests
         {
             try
             {
-                var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32);
-                Console.WriteLine("Unicorn version: {0}", u.Version());
+                using (var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32))
+                {
+                    Console.WriteLine("Unicorn version: {0}", u.Version());
 
-                // map 2MB of memory for this emulation
-                u.MemMap(address, new UIntPtr(2 * 1024 * 1024), Common.UC_PROT_ALL);
+                    // map 2MB of memory for this emulation
+                    u.MemMap(address, new UIntPtr(2 * 1024 * 1024), Common.UC_PROT_ALL);
 
-                // write machine code to be emulated to memory
-                u.MemWrite(address, code);
+                    // write machine code to be emulated to memory
+                    u.MemWrite(address, code);
 
-                // initialize machine registers
-                u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000));
+                    // initialize machine registers
+                    u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000));
 
-                // tracing all instructions by having @begin > @end
-                u.AddCodeHook(CodeHookCallback, null, 1, 0);
+                    // tracing all instructions by having @begin > @end
+                    u.AddCodeHook(CodeHookCallback, null, 1, 0);
 
-                // handle interrupt ourself
-                u.AddInterruptHook(InterruptHookCallback, null);
+                    // handle interrupt ourself
+                    u.AddInterruptHook(InterruptHookCallback, null);
 
-                // handle SYSCALL
-                u.AddSyscallHook(SyscallHookCallback, null);
+                    // handle SYSCALL
+                    u.AddSyscallHook(SyscallHookCallback, null);
 
-                Console.WriteLine(">>> Start tracing linux code");
+                    Console.WriteLine(">>> Start tracing linux code");
 
-                // emulate machine code in infinite time
-                u.EmuStart(address, address + (UInt64)code.Length, 0u, new UIntPtr(0));
+                    // emulate machine code in infinite time
+                    u.EmuStart(address, address + (UInt64)code.Length, 0u, new UIntPtr(0));
 
-                Console.WriteLine(">>> Emulation Done!");
+                    Console.WriteLine(">>> Emulation Done!");
+                }
             }
             catch (UnicornEngineException ex)
             {
diff --git a/bindings/dotnet/UnicornTests/UnicornTests.csproj b/bindings/dotnet/UnicornTests/UnicornTests.csproj
index dfb6bdf1..1c8a9278 100644
--- a/bindings/dotnet/UnicornTests/UnicornTests.csproj
+++ b/bindings/dotnet/UnicornTests/UnicornTests.csproj
@@ -9,9 +9,10 @@
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>UnicornTests</RootNamespace>
     <AssemblyName>UnicornTests</AssemblyName>
-    <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>x86</PlatformTarget>
@@ -22,6 +23,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>