Haskell 中的 STM 和 unsafePerformIO

STM and unsafePerformIO in Haskell

documentation for STM 指出:

Using unsafePerformIO inside of atomically is also dangerous but for different reasons. See unsafeIOToSTM for more on this.

当涉及到使用线程和异步异常时,有一些函数可以屏蔽异步异常,以便可以安全地分配和释放资源。

但是有很多函数在幕后使用了unsafePerformIO,例如memory包中的allocAndFreeze,并且不难强制包含这样一个表达式的thunk在 STM 交易中。这些函数在 STM 交易中使用真的安全吗?是否存在可能导致内存泄漏或数据损坏的情况?对于这种情况,是否有等同于 mask 的东西?

谢谢

如果 IO 被 STM retry.这有两个原因:首先,STM 重试没有 运行 异常处理程序,因此如果不安全的 IO 依赖异常处理程序释放资源(例如使用 bracket),它们将不会被清理;其次,IO 可能会在任何时候被中断或执行多次,因此您需要确保它即使被中断也能保持程序不变性。

所以例如 allocAndFreeze 不会泄漏,因为它在内部使用 ForeignPtr,在 GHC 中它只是固定在托管堆中的内存,所以它不依赖于异常处理程序或终结器回收内存。但是,它 可能 导致数据损坏,如果不安全的 IO 暂时破坏数据结构中的不变量,例如“分配的数组必须始终排序”,那么这种破坏可能会变得可见如果计算在那一点中断。