parent
5a7614dee1
commit
a5e393b018
|
@ -1040,75 +1040,79 @@ Except for the `stackalloc` operator, C# provides no predefined constructs for m
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public unsafe class Memory
|
||||
public static unsafe class Memory
|
||||
{
|
||||
// Handle for the process heap. This handle is used in all calls to the
|
||||
// HeapXXX APIs in the methods below.
|
||||
static int ph = GetProcessHeap();
|
||||
|
||||
// Private instance constructor to prevent instantiation.
|
||||
private Memory() {}
|
||||
private static readonly IntPtr s_heap = GetProcessHeap();
|
||||
|
||||
// Allocates a memory block of the given size. The allocated memory is
|
||||
// automatically initialized to zero.
|
||||
public static void* Alloc(int size) {
|
||||
void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size);
|
||||
public static void* Alloc(int size)
|
||||
{
|
||||
void* result = HeapAlloc(s_heap, HEAP_ZERO_MEMORY, (UIntPtr)size);
|
||||
if (result == null) throw new OutOfMemoryException();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Copies count bytes from src to dst. The source and destination
|
||||
// blocks are permitted to overlap.
|
||||
public static void Copy(void* src, void* dst, int count) {
|
||||
public static void Copy(void* src, void* dst, int count)
|
||||
{
|
||||
byte* ps = (byte*)src;
|
||||
byte* pd = (byte*)dst;
|
||||
if (ps > pd) {
|
||||
if (ps > pd)
|
||||
{
|
||||
for (; count != 0; count--) *pd++ = *ps++;
|
||||
}
|
||||
else if (ps < pd) {
|
||||
else if (ps < pd)
|
||||
{
|
||||
for (ps += count, pd += count; count != 0; count--) *--pd = *--ps;
|
||||
}
|
||||
}
|
||||
|
||||
// Frees a memory block.
|
||||
public static void Free(void* block) {
|
||||
if (!HeapFree(ph, 0, block)) throw new InvalidOperationException();
|
||||
public static void Free(void* block)
|
||||
{
|
||||
if (!HeapFree(s_heap, 0, block)) throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
// Re-allocates a memory block. If the reallocation request is for a
|
||||
// larger size, the additional region of memory is automatically
|
||||
// initialized to zero.
|
||||
public static void* ReAlloc(void* block, int size) {
|
||||
void* result = HeapReAlloc(ph, HEAP_ZERO_MEMORY, block, size);
|
||||
public static void* ReAlloc(void* block, int size)
|
||||
{
|
||||
void* result = HeapReAlloc(s_heap, HEAP_ZERO_MEMORY, block, (UIntPtr)size);
|
||||
if (result == null) throw new OutOfMemoryException();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the size of a memory block.
|
||||
public static int SizeOf(void* block) {
|
||||
int result = HeapSize(ph, 0, block);
|
||||
public static int SizeOf(void* block)
|
||||
{
|
||||
int result = (int)HeapSize(s_heap, 0, block);
|
||||
if (result == -1) throw new InvalidOperationException();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Heap API flags
|
||||
const int HEAP_ZERO_MEMORY = 0x00000008;
|
||||
private const int HEAP_ZERO_MEMORY = 0x00000008;
|
||||
|
||||
// Heap API functions
|
||||
[DllImport("kernel32")]
|
||||
static extern int GetProcessHeap();
|
||||
private static extern IntPtr GetProcessHeap();
|
||||
|
||||
[DllImport("kernel32")]
|
||||
static extern void* HeapAlloc(int hHeap, int flags, int size);
|
||||
private static extern void* HeapAlloc(IntPtr hHeap, int flags, UIntPtr size);
|
||||
|
||||
[DllImport("kernel32")]
|
||||
static extern bool HeapFree(int hHeap, int flags, void* block);
|
||||
private static extern bool HeapFree(IntPtr hHeap, int flags, void* block);
|
||||
|
||||
[DllImport("kernel32")]
|
||||
static extern void* HeapReAlloc(int hHeap, int flags, void* block, int size);
|
||||
private static extern void* HeapReAlloc(IntPtr hHeap, int flags, void* block, UIntPtr size);
|
||||
|
||||
[DllImport("kernel32")]
|
||||
static extern int HeapSize(int hHeap, int flags, void* block);
|
||||
private static extern UIntPtr HeapSize(IntPtr hHeap, int flags, void* block);
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1117,18 +1121,21 @@ An example that uses the `Memory` class is given below:
|
|||
```csharp
|
||||
class Test
|
||||
{
|
||||
static void Main() {
|
||||
unsafe {
|
||||
byte* buffer = (byte*)Memory.Alloc(256);
|
||||
try {
|
||||
for (int i = 0; i < 256; i++) buffer[i] = (byte)i;
|
||||
byte[] array = new byte[256];
|
||||
fixed (byte* p = array) Memory.Copy(buffer, p, 256);
|
||||
}
|
||||
finally {
|
||||
Memory.Free(buffer);
|
||||
}
|
||||
for (int i = 0; i < 256; i++) Console.WriteLine(array[i]);
|
||||
static unsafe void Main()
|
||||
{
|
||||
byte* buffer = null;
|
||||
try
|
||||
{
|
||||
const int Size = 256;
|
||||
buffer = (byte*)Memory.Alloc(Size);
|
||||
for (int i = 0; i < Size; i++) buffer[i] = (byte)i;
|
||||
byte[] array = new byte[Size];
|
||||
fixed (byte* p = array) Memory.Copy(buffer, p, Size);
|
||||
for (int i = 0; i < Size; i++) Console.WriteLine(array[i]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer != null) Memory.Free(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue