/// <summary> /// Allocates a block of memory from the default process heap. /// </summary> /// <param name="size">The size of the memory to allocate.</param> /// <param name="allocationFlags">The memory allocation flags.</param> /// <returns>A pointer to the allocated block of memory.</returns> public static IntPtr Allocate(ulong size, MemoryAllocationFlags allocationFlags) { if (hHeap == IntPtr.Zero) { InitializeHeap(); } bool zeroFill = (allocationFlags & MemoryAllocationFlags.ZeroFill) == MemoryAllocationFlags.ZeroFill; IntPtr block = SafeNativeMethods.HeapAlloc(hHeap, zeroFill ? NativeConstants.HEAP_ZERO_MEMORY : 0U, new UIntPtr(size)); if (block == IntPtr.Zero) { if ((allocationFlags & MemoryAllocationFlags.ReturnZeroOnOutOfMemory) == MemoryAllocationFlags.ReturnZeroOnOutOfMemory) { return(IntPtr.Zero); } else { throw new OutOfMemoryException(); } } if (size > 0L) { MemoryPressureManager.AddMemoryPressure((long)size); } return(block); }
/// <summary> /// Frees a block of memory previously allocated with Allocate(). /// </summary> /// <param name="block">The block to free.</param> /// <exception cref="InvalidOperationException">There was an error freeing the block.</exception> public static void Free(IntPtr block) { if (Memory.hHeap != IntPtr.Zero) { long bytes = (long)SafeNativeMethods.HeapSize(hHeap, 0, block); bool result = SafeNativeMethods.HeapFree(hHeap, 0, block); if (!result) { int error = Marshal.GetLastWin32Error(); throw new InvalidOperationException("HeapFree returned an error: " + error.ToString(CultureInfo.InvariantCulture)); } if (bytes > 0) { MemoryPressureManager.RemoveMemoryPressure(bytes); } } else { #if REPORTLEAKS throw new InvalidOperationException("memory leak! check the debug output for more info, and http://blogs.msdn.com/ricom/archive/2004/12/10/279612.aspx to track it down"); #endif } }
/// <summary> /// Frees the block of memory allocated by AllocateExecutable(). /// </summary> /// <param name="hMem">The block to free.</param> /// <param name="size">The size of the allocated block.</param> public static void FreeExecutable(IntPtr hMem, long size) { if (!SafeNativeMethods.VirtualFree(hMem, UIntPtr.Zero, NativeConstants.MEM_RELEASE)) { int error = Marshal.GetLastWin32Error(); throw new InvalidOperationException("VirtualFree returned an error: " + error.ToString(CultureInfo.InvariantCulture)); } if (size > 0L) { MemoryPressureManager.RemoveMemoryPressure(size); } }
/// <summary> /// Frees a block of memory previous allocated with AllocateLarge(). /// </summary> /// <param name="block">The block to free.</param> /// <param name="bytes">The size of the block.</param> public static void FreeLarge(IntPtr block, ulong bytes) { if (!SafeNativeMethods.VirtualFree(block, UIntPtr.Zero, NativeConstants.MEM_RELEASE)) { int error = Marshal.GetLastWin32Error(); throw new InvalidOperationException("VirtualFree returned an error: " + error.ToString(CultureInfo.InvariantCulture)); } if (bytes > 0) { MemoryPressureManager.RemoveMemoryPressure((long)bytes); } }
/// <summary> /// Allocates a block of memory with the PAGE_EXECUTE permission. /// </summary> /// <param name="size">The size of the memory to allocate.</param> /// <returns>A pointer to the allocated block of memory.</returns> public static IntPtr AllocateExecutable(long size) { IntPtr block = SafeNativeMethods.VirtualAlloc(IntPtr.Zero, new UIntPtr((ulong)size), NativeConstants.MEM_COMMIT, NativeConstants.PAGE_EXECUTE_READWRITE); if (block == IntPtr.Zero) { throw new OutOfMemoryException("VirtualAlloc returned a null pointer"); } if (size > 0L) { MemoryPressureManager.AddMemoryPressure(size); } return(block); }
/// <summary> /// Allocates a block of memory at least as large as the amount requested. /// </summary> /// <param name="bytes">The number of bytes you want to allocate.</param> /// <returns>A pointer to a block of memory at least as large as bytes</returns> /// <remarks> /// This method uses an alternate method for allocating memory (VirtualAlloc in Windows). The allocation /// granularity is the page size of the system (usually 4K). Blocks allocated with this method may also /// be protected using the ProtectBlock method. /// </remarks> public static IntPtr AllocateLarge(ulong bytes) { IntPtr block = SafeNativeMethods.VirtualAlloc(IntPtr.Zero, new UIntPtr(bytes), NativeConstants.MEM_COMMIT, NativeConstants.PAGE_READWRITE); if (block == IntPtr.Zero) { throw new OutOfMemoryException("VirtualAlloc returned a null pointer"); } if (bytes > 0) { MemoryPressureManager.AddMemoryPressure((long)bytes); } return(block); }
/// <summary> /// Frees the block of memory allocated by Allocate(). /// </summary> /// <param name="hMem">The block to free.</param> public static void Free(IntPtr hMem) { if (hHeap != IntPtr.Zero) { long size = Size(hMem); if (!SafeNativeMethods.HeapFree(hHeap, 0, hMem)) { int error = Marshal.GetLastWin32Error(); throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "HeapFree returned an error 0x{0:X8}", error)); } if (size > 0L) { MemoryPressureManager.RemoveMemoryPressure(size); } } }
/// <summary> /// Allocates a block of memory at least as large as the amount requested. /// </summary> /// <param name="bytes">The number of bytes you want to allocate.</param> /// <returns>A pointer to a block of memory at least as large as <b>bytes</b>.</returns> /// <exception cref="OutOfMemoryException">Thrown if the memory manager could not fulfill the request for a memory block at least as large as <b>bytes</b>.</exception> public static IntPtr Allocate(ulong bytes) { if (hHeap == IntPtr.Zero) { CreateHeap(); } // Always initialize the memory to zero. // This ensures that the behavior of Allocate is the same as AllocateLarge. // AllocateLarge uses VirtualAlloc which is documented to initialize the allocated memory to zero. IntPtr block = SafeNativeMethods.HeapAlloc(hHeap, NativeConstants.HEAP_ZERO_MEMORY, new UIntPtr(bytes)); if (block == IntPtr.Zero) { throw new OutOfMemoryException("HeapAlloc returned a null pointer"); } if (bytes > 0) { MemoryPressureManager.AddMemoryPressure((long)bytes); } return(block); }
/// <summary> /// Resizes the memory block previously allocated by Allocate(). /// </summary> /// <param name="pv">The pointer to the block to resize.</param> /// <param name="newSize">The new size of the block.</param> /// <returns>The pointer to the resized block.</returns> public static IntPtr ReAlloc(IntPtr pv, long newSize) { if (hHeap == IntPtr.Zero) { InitializeHeap(); } IntPtr block; long oldSize = Size(pv); try { UIntPtr bytes = new UIntPtr((ulong)newSize); block = SafeNativeMethods.HeapReAlloc(hHeap, 0U, pv, bytes); } catch (OverflowException ex) { throw new OutOfMemoryException(string.Format(CultureInfo.InvariantCulture, "Overflow while trying to allocate {0:N} bytes", newSize), ex); } if (block == IntPtr.Zero) { throw new OutOfMemoryException(string.Format(CultureInfo.InvariantCulture, "HeapAlloc returned a null pointer while trying to allocate {0:N} bytes", newSize)); } if (oldSize > 0L) { MemoryPressureManager.RemoveMemoryPressure(oldSize); } if (newSize > 0) { MemoryPressureManager.AddMemoryPressure(newSize); } return(block); }
/// <summary> /// Resizes the memory block previously allocated by Allocate(). /// </summary> /// <param name="pv">The pointer to the block to resize.</param> /// <param name="newSize">The new size of the block.</param> /// <returns>The pointer to the resized block.</returns> public static IntPtr ReAlloc(IntPtr pv, int newSize) { if (hHeap == IntPtr.Zero) { InitializeHeap(); } IntPtr block; long oldSize = Size(pv); try { UIntPtr bytes = new UIntPtr((ulong)newSize); block = SafeNativeMethods.HeapReAlloc(hHeap, 0U, pv, bytes); } catch (OverflowException) { throw new OutOfMemoryException(); } if (block == IntPtr.Zero) { throw new OutOfMemoryException(); } if (oldSize > 0L) { MemoryPressureManager.RemoveMemoryPressure(oldSize); } if (newSize > 0) { MemoryPressureManager.AddMemoryPressure(newSize); } return(block); }