【发布时间】:2020-05-09 09:09:13
【问题描述】:
我的代码中有这个功能,它似乎工作得很好:
-- type declaration just for reference, i don't have it in my actual code
retrieveVulkanArray :: Storable a => (Ptr Word32 -> Ptr a -> IO b) -> IO (Ptr a, Int)
retrieveVulkanArray' f =
alloca $ \arrCount -> do
f arrCount vkNullPtr
arrCount' <- fromIntegral <$> peek arrCount
allocaArray arrCount' $ \resArray -> do
f arrCount resArray
pure (resArray, arrCount')
(对于上下文,这是一个从 Vulkan API 获取 FFI 数组的辅助函数,例如 f 可能是 vkEnumeratePhysicalDevices)
当我查看我的代码时,我注意到它向调用者返回了 resArray(从 allocaArray 的描述来看,它似乎只在内部 lambda 中有效)。在 C 中,这样的代码将是未定义的行为。我的直觉在这里是正确的还是有更多的事情发生?毕竟我还没有注意到任何崩溃:)
【问题讨论】:
-
我认为这是 UB。您正在返回一个指向内存 (
resArray) 的指针。您可以使用非“alloca”分配函数并让调用者在正确的时间释放它。 (或者也许是一个外部指针) -
我是这么认为的。我想没有访问冲突可以解释为 GC 直到一段时间后才真正释放内存?
-
很难说。内存在被释放时可能不会立即返回给操作系统,因此它保持可用但可以被其他分配器重用。这也发生在许多 C 实现中:如果你 free() 一个指针并立即访问它,它可能不会导致访问冲突,因为内存并不总是返回给操作系统,特别是如果它是一个小内存区域。
-
您应该始终在您的代码中添加函数类型签名,以便其他人阅读您的代码,并在您将来阅读自己的代码时为您自己着想。
-- type declaration just for reference, i don't have it in my actual code
标签: haskell memory-management monads haskell-ffi