所以我明白interior_ptr<typename>
可以使用 fixed
来操作结构数组,就像在 C♯ 中一样。语句,但它不会将数组固定在堆上,而是让垃圾收集器四处移动它。这很好,因为我不想妨碍垃圾收集器有效工作。然而,垃圾收集器在一个单独的线程上运行,当它处于事件状态时,所有其他线程都会停止,同时压缩堆上的对象。
假设我有以下代码:
interior_ptr<unsigned char> sourceBufferPtr = reinterpret_cast<interior_ptr<unsigned char>>(&sourceBuffer[0]) + sourceOffset;
代码应该这样运行,例如:
-
&sourceBuffer[0]
返回数组中第一项的地址:32。 -
sourceOffset
: 8. -
reinterpret_cast<interior_ptr<unsigned char>>(&sourceBuffer[0])
将地址转换为interior_ptr<unsigned char>
, 它被添加到sourceOffset
. -
sourceBufferPtr
应该等于……- 如果垃圾收集器没有移动数组则为 40。
- 如果垃圾收集器将数组移动到 16 这样的位置,则为 24。
- of 40 如果垃圾收集器在第 3 步和第 4 步之间移动数组,那么在第 3 步之后数组的位置将更新为 16,但结果分配给
sourceBufferPtr
仍然是 40 岁。
我假设垃圾收集器可以在步骤 3 和 4 之间停止线程并可能将错误的值分配给 sourceBufferPtr
是否正确?或者公共(public)语言运行时是否以某种方式知道如何确保整个语句是原子的/值是正确的?用 interior_ptr<typename>
做什么是安全的?
最佳答案
Am I correct to assume that the garbage collector could stop the thread between steps 3 and 4 and possibly assign the wrong value to sourceBufferPtr?
是的,因为您的代码不正确。通过使用 reinterpret_cast 在获得指向数组元素的 unmaanged 指针之后,您为 GC 引入了一个使指针无效的机会窗口。您需要像这样不间断地使用 interior_ptr:
interior_ptr<unsigned char> bufferPtr = &sourceBuffer[0];
interior_ptr<unsigned char> sourceBufferPtr = bufferPtr + sourceOffset;
在这个新代码中,只有 interior_ptr。即使是第二个赋值右侧的临时变量也是一个 interior_ptr。
关于.NET 垃圾收集、C++/CLI interior_ptr 和线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10668931/