我正在做一些研究,我实现了一个简单的内存管理器系统来查看进程的行为,但我注意到了MemoryHelper类的免费方法,以及" Marshal.FreeHGlobal"没有意识到内存中的空闲,即使在释放内存后也可能访问数据......
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication3
{
public unsafe static class MemoryHelper
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcessHeap();
[DllImport("kernel32.dll", SetLastError = false)]
static extern void* HeapAlloc(IntPtr hHeap, uint dwFlags, UIntPtr dwBytes);
[DllImport("kernel32.dll")]
static extern void* HeapReAlloc(IntPtr hHeap, uint dwFlags, IntPtr lpMem, UIntPtr dwBytes);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool HeapFree(IntPtr hHeap, uint dwFlags, void* lpMem);
private static uint HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010;
private static uint HEAP_NO_SERIALIZE = 0x00000001;
private static uint HEAP_ZERO_MEMORY = 0x00000008;
private static IntPtr Handle { get; set; } = GetProcessHeap();
public static void* Malloc(uint size)
{
var tmp = HeapAlloc(Handle, HEAP_ZERO_MEMORY, new UIntPtr(size));
if (tmp == null)
throw new Exception("Fail to allocate memory");
return tmp;
}
public static void* Realloc(IntPtr blk, uint newSize)
{
var tmp = HeapReAlloc(Handle, HEAP_REALLOC_IN_PLACE_ONLY, blk, new UIntPtr(newSize));
if (tmp == null)
throw new Exception("Fail to reallocate memory");
return tmp;
}
public static bool Free(void* blk)
{
var ret = HeapFree(Handle, HEAP_NO_SERIALIZE, blk);
if (!ret)
throw new Exception("Fail to free memory");
return ret;
}
}
unsafe public class Study
{
public Study()
{
UsingManualMemoryClass();
Console.WriteLine("".PadLeft(80, '='));
UsingMarshalClass();
}
private static readonly object LockObj = new object();
public void UsingManualMemoryClass()
{
int tamanho = 20;
int* teste = (int*)MemoryHelper.Malloc((uint)(sizeof(int) * tamanho));
Random rnd = new Random();
lock (LockObj)
{
for (int i = 0; i < tamanho; i++)
teste[i] = rnd.Next(0,8000);
}
for (int i = 0; i < tamanho; i++)
Console.WriteLine(teste[i]);
MemoryHelper.Free(teste);
Console.WriteLine("".PadLeft(80, '-'));
for (int i = 0; i < tamanho; i++)
Console.WriteLine(teste[i]);
}
public void UsingMarshalClass()
{
int tamanho = 20;
int* teste = (int*)Marshal.AllocHGlobal(sizeof(int) * tamanho);
Random rnd = new Random();
lock (LockObj)
{
for (int i = 0; i < tamanho; i++)
teste[i] = rnd.Next(0, 8000);
}
for (int i = 0; i < tamanho; i++)
Console.WriteLine(teste[i]);
Marshal.FreeHGlobal((IntPtr)teste);
Console.WriteLine("".PadLeft(80, '-'));
for (int i = 0; i < tamanho; i++)
Console.WriteLine(teste[i]);
}
}
class Program
{
static void Main(string[] args)
{
new Study();
}
}
}
为什么会这样?
-----编辑
我在codeproject找到了这篇文章,我得到了C ++ / CLI代码,用代码创建了一个简单的DLL并做了一些更改,以使用本机C运行时来分配和释放内存
#include <malloc.h>
#include <stdlib.h>>
using namespace System;
namespace mm
{
public ref class Unmanaged abstract sealed
{
public:
generic <typename T> where T : value class
static void* New(int elementCount)
{
return malloc(sizeof(T) * elementCount);
}
static void Free(void* unmanagedPointer)
{
free(unmanagedPointer);
}
generic <typename T> where T : value class
static void* Resize(void* oldPointer, int newElementCount)
{
return realloc(oldPointer, (int)sizeof(T) * newElementCount);
}
};
}
使用本机C函数执行此操作后,我无法在免费...
之后访问内存答案 0 :(得分:0)
Marshal.FreeHGlobal
调用Win32 API函数LocalFree
。如果在调用LocalFree
后尝试访问内存,则调用未定义的行为。一些可能的结果:
几乎任何事情都可能发生,你不能依赖任何东西。
你的错误是推断释放后能够访问内存意味着内存尚未被释放。这种合理的推论是错误的。