c# - 提升指针后释放 IntPtr 分配的内存

标签 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;
    }

最佳答案

您必须创建原始指针的拷贝,供以后使用。在这种情况下,它被称为电流:

    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 block 中。如果指针不为零,则在 finally block 中再次释放内存块:

    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;
    }

关于c# - 提升指针后释放 IntPtr 分配的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23948947/

相关文章:

c# - InvariantCulture 中使用的日期时间格式

c# - 我可以使用 Html.Raw 为卡片套装设置单字母代码吗?

c# - 如何轻松地将两个异步请求链接在一起?

c++ - 如果基类析构函数是虚拟的,则派生类的析构函数默认是虚拟的吗?

c++ - 将结构传递给构造函数

c# - 为什么在 web api 方法中返回接口(interface)时,我得到的是具有接口(interface)值的继承类的值?

c# - 跟踪谁在 C# 应用程序或 SQL Server 中对 SQL Server 进行了更改

c++ - 创建 C++ 类的 stub 版本

c++ - boost 图错误

c++ - 我可以从崩溃签名获取源代码(Windows崩溃报告)