c# - 如何在包含本机内存的类上实现 AsSpan()?
问题描述
我有一个包含一些本机内存的类型。我想AsSpan()
在它上面实现,以便可以安全地访问本机内存。
下面是一个天真的尝试,它显示了我正在尝试做的事情。显然Span<T>
不会让持有者对象保持活动状态,因为它只有指向本机内存的指针,而不是对持有者对象的引用。我也尝试过实现MemoryManager<T>
,但我也看不到如何使Span<T>
管理器对象保持活动状态。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
internal class Program
{
public static void Main()
{
Span<byte> span = GetSpan();
GC.Collect();
GC.WaitForPendingFinalizers();
span[span.Length - 1] = 0; // Access violation
}
private static Span<byte> GetSpan()
{
Span<byte> span = new Holder(1 << 20).AsSpan();
GC.Collect();
GC.WaitForPendingFinalizers();
span[span.Length - 1] = 0; // OK
return span;
}
}
public class Holder
{
private readonly int _size;
private readonly IntPtr _pointer;
public Holder(int size)
{
_size = size;
_pointer = Marshal.AllocHGlobal(_size);
}
~Holder()
{
Marshal.FreeHGlobal(_pointer);
Debug.WriteLine("{0:X} was freed", _pointer);
}
public Span<byte> AsSpan()
{
unsafe { return new Span<byte>((void*)_pointer, _size); }
}
}
Span<T>
能够保持被管理的对象像String
或byte[]
活着。有没有办法AsSpan()
在本机内存持有者类型上实现,以便 Span<T>
让持有者对象保持活动状态?
解决方案
根据这个讨论,非托管内存的生命周期无法使用Span<T>
.
您可以实现MemoryManager<T>
管理非托管内存的生命周期,在一个using
块中使用它,只要Span<T>
不逃逸 using 块,它就是安全的。(但不可能强制 API 使用者安全使用 API。)
推荐阅读
- c - 运行外部编译器 (godbolt) 程序集
- node.js - ExperimentalWarning:条件导出是一项实验性功能"
- netlogo - 子样本中的海龟做出不同的动作
- c++ - 不释放内部单元时内存泄漏?
- woocommerce - 更新订单状态的 Dokan 操作
- bitnami - Bitnami 中的 server.js 在哪里?
- apache - Apache 无法使用 ProxyPass 托管 ASP.NET Core 应用程序
- mysql - 在where子句MySQL中转换日期
- linux - 如何在一台服务器中的 Apache 和另一台服务器中的 Tomcat 之间配置 AJP
- ios - 布局帮助适合任何屏幕