zoukankan      html  css  js  c++  java
  • 使用CopyMemory API出现 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

    迁移一个旧程序到.net. 之前有段代码是这样的.

    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    
            For n = 0 To 4
                    
                    lbt(0) = strRead(n * 4 + 3 + 3)
                    lbt(1) = strRead(n * 4 + 3 + 2)
                    lbt(2) = strRead(n * 4 + 3 + 1)
                    lbt(3) = strRead(n * 4 + 3)
                    CopyMemory ByVal VarPtr(fTempData(n)), ByVal VarPtr(lbt(0)), 4
            Next

    直接翻译成C#, 结果运行时报错  尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

     [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", CharSet = CharSet.Ansi)]
            public extern static long CopyMemory(IntPtr dest, IntPtr source, int size);  
    
                for (n = 0; n <= 4; n++)
                {
        
                    lbt[0] = bytRead[n * 4 + 3 + 3];
                    lbt[1] = bytRead[n * 4 + 3 + 2];
                    lbt[2] = bytRead[n * 4 + 3 + 1];
                    lbt[3] = bytRead[n * 4 + 3];
    
                    CopyMemory ((IntPtr)(fTempData[n]), (IntPtr)(lbt[0]), 4);
                }

      其实这段代码是字节数组转浮点数, 可以用这句代码就可以了 fTempData[n] = BitConverter.ToSingle(lbt, 0);

    也可以用  System.Buffer.BlockCopy(lbt, 0, fTempData, 0, 4);  这个不涉及unsafe操作

    但这个涉及到内存操作, 之前都没研究过C# unsafe的内存操作. 我还以为只要在项目里打开允许不安全代码.函数里加上unsafe关键字就可以了.结果不是的.

    在MSDN找到一段例子

    static void Main()
        {
    
            // Create a point struct.
            Point p;
            p.x = 1;
            p.y = 1;
    
            Console.WriteLine("The value of first point is " + p.x + " and " + p.y + ".");
    
            // Initialize unmanged memory to hold the struct.
            IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(p));
    
            try
            {
    
                // Copy the struct to unmanaged memory.
                Marshal.StructureToPtr(p, pnt, false);
    
                // Create another point.
                Point anotherP;
    
                // Set this Point to the value of the
                // Point in unmanaged memory.
                anotherP = (Point)Marshal.PtrToStructure(pnt, typeof(Point));
    
                Console.WriteLine("The value of new point is " + anotherP.x + " and " + anotherP.y + ".");
    
            }
            finally
            {
                // Free the unmanaged memory.
                Marshal.FreeHGlobal(pnt);
            }
    
    
    
        }

     一个Memory的类

    using System;
    using System.Runtime.InteropServices;
    
    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.
        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(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)
        {
            byte* ps = (byte*)src;
            byte* pd = (byte*)dst;
            if (ps > pd)
            {
                for (; count != 0; count--) *pd++ = *ps++;
            }
            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(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(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 = (int)HeapSize(s_heap, 0, block);
            if (result == -1) throw new InvalidOperationException();
            return result;
        }
    
        // Heap API flags
        private const int HEAP_ZERO_MEMORY = 0x00000008;
    
        // Heap API functions
        [DllImport("kernel32")]
        private static extern IntPtr GetProcessHeap();
    
        [DllImport("kernel32")]
        private static extern void* HeapAlloc(IntPtr hHeap, int flags, UIntPtr size);
    
        [DllImport("kernel32")]
        private static extern bool HeapFree(IntPtr hHeap, int flags, void* block);
    
        [DllImport("kernel32")]
        private static extern void* HeapReAlloc(IntPtr hHeap, int flags, void* block, UIntPtr size);
    
        [DllImport("kernel32")]
        private static extern UIntPtr HeapSize(IntPtr hHeap, int flags, void* block);
    }
    View Code
    class Test
    {
        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);
            }
        }
    }

    https://stackoverflow.com/questions/2658380/how-can-i-copy-unmanaged-data-in-c-sharp-and-how-fast-is-it

  • 相关阅读:
    记CentOS-7-x86_64-DVD-1503与Windows7单硬盘双系统的安装
    NetCFSvcUtil.exe and Windows 7
    qq 通信原理(转)
    Qt通过odbc读取excel数据
    Qt中gb2312/GBK的URL编解码函数
    Qt将表格table保存为excel(odbc方式)
    Qt根据类名创建对象(元对象反射)
    亲试,Windows平台上使用Qt5.2.1编写Android
    使用正则表达式限制swing (JTextField等) 的输入
    Winform的"透明"
  • 原文地址:https://www.cnblogs.com/zitjubiz/p/13946915.html
Copyright © 2011-2022 走看看