在提升指针后释放IntPtr分配内存

时间:2014-05-30 07:06:23

标签: c# c++

我在C#中使用IntPtr,从C ++项目中获取对象数组。

为此,我分配了Marshal.AllocHGlobal方法所需的内存,并且我将C ++中的完整数组复制到ptr中。

问题是我正在推广指针,移动到数组中的下一个对象。

我的问题是: 在使用Marshal.FreeHGlobal方法之前,我是否必须恢复IntPtr的第一个值?

这是代码

public List<DirEntry> getDirEntries()
    {
            int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
            int bufferSize = 28 * dirEntrySize;
            IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
            CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);

            DirEntry dirEntry = new DirEntry();
            List<DirEntry> dirEntries = new List<DirEntry>();
            for (int i = 0; i < 28; i++)
            {
                Marshal.PtrToStructure(buffer, dirEntry);
                buffer += dirEntrySize;
            }

            Marshal.FreeHGlobal(buffer);
            return dirEntries;
    }

1 个答案:

答案 0 :(得分:2)

您必须创建原始指针的副本,以后可以使用。在这种情况下,它被称为current:

    public List<DirEntry> getDirEntries()
    {
        int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
        int bufferSize = 28 * dirEntrySize;
        IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
        CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);

        IntPtr current = buffer;

        DirEntry dirEntry = new DirEntry();
        List<DirEntry> dirEntries = new List<DirEntry>();
        for (int i = 0; i < 28; i++)
        {
            Marshal.PtrToStructure(current, dirEntry);
            current += dirEntrySize;
        }

        Marshal.FreeHGlobal(buffer);
        return dirEntries;
    }

但是,如果不使用指针的显式副本,则可以使用IntPtr.Add()

    public List<DirEntry> getDirEntries()
    {
        int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
        int bufferSize = 28 * dirEntrySize;
        IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
        CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);

        DirEntry dirEntry = new DirEntry();
        List<DirEntry> dirEntries = new List<DirEntry>();
        for (int i = 0; i < 28; i++)
        {
            Marshal.PtrToStructure(IntPtr.Add(buffer, i * dirEntrySize), dirEntry);
        }

        Marshal.FreeHGlobal(buffer);
        return dirEntries;
    }

请记住,您的代码包含潜在的内存韭菜。您应该将代码包装在try / finally块中。在finally块中,如果指针不为零,则再次释放内存块:

    public List<DirEntry> getDirEntries()
    {
        int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
        int bufferSize = 28 * dirEntrySize;
        IntPtr buffer = Marshal.AllocHGlobal(bufferSize);

        try
        {
            CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);

            DirEntry dirEntry = new DirEntry();
            List<DirEntry> dirEntries = new List<DirEntry>();
            for (int i = 0; i < 28; i++)
            {
                Marshal.PtrToStructure(IntPtr.Add(buffer, i * dirEntrySize), dirEntry);
            }
        }
        finally
        {
            if (buffer != IntPtr.Zero)
                Marshal.FreeHGlobal(buffer);
        }


        return dirEntries;
    }