如何在Memory <t> .Span中取消固定内存?

时间:2019-03-13 22:27:18

标签: c# memory-management heap-memory

我相信以下两段代码应该等效:

df = (pd.DataFrame(d)
      .stack()
      .reset_index()
      .rename({'level_0': 'Column2', 'level_1': 'Column1', 0: 'Column3'}, axis=1)
      .sort_index(1).sort_values('Column1'))

print(df)


  Column1                 Column2  Column3
0    Jill  Avenger: Age of Ultron      7.0
2    Jill        Django Unchained      6.5
4    Jill               Gone Girl      9.0
5    Jill      Kill the Messenger      8.0
1    Toby  Avenger: Age of Ultron      8.5
3    Toby        Django Unchained      9.0
6    Toby               Zoolander      2.0

两个代码都将打印“ H”。

我不了解的是第二个示例中的内存解除固定位置。

据我了解,字符串是在堆上分配的,// first example string s = "Hello memmory"; ReadOnlyMemory<char> memory = s.AsMemory(); using (MemoryHandle pin = memory.Pin()) { Span<char> span = new Span<char>(pin.Pointer, 1); Console.WriteLine(span[0]); } // second example ReadOnlySpan<char> span2 = memory.Span; Console.WriteLine(span2[0]); 固定它并从指针创建Span。 MemoryHandle解除锁定。

我相信MemoryHandle.Dispose也必须固定内存,否则span无法访问指针。但是在第二个示例中如何取消固定内存?

2 个答案:

答案 0 :(得分:1)

最后一个假设是错误的:memory.Span不需要固定内存,因为垃圾回收器知道其底层引用。如果您希望将指针传递给本机API,则可以单独使用固定功能。

答案 1 :(得分:0)

Span仅驻留在当前方法线程的堆栈上,而不驻留在其方法的堆上,因此只要您在其中使用它,它就将一直存在。到目前为止很清楚。

现在有趣的部分:

一个清楚的事实是,memory.Span的结果不是固定的,而仅是通过使用ref T内的Span<T>来引用的。 GarbageCollector。

只要您的记忆一直存在,您的跨度也将因此而跨度。

参考文献:

https://msdn.microsoft.com/en-us/magazine/mt814808.aspx?f=255&MSPPError=-2147217396 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref#ref-struct-types