Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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
            }
        }
Пример #3
0
        /// <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);
            }
        }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <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);
                }
            }
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        /// <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);
        }