初始化期间指针/外部指针的垃圾收集

Garbage collection of pointers / foreign pointers during initialization

我正在使用 Data.ByteString.Internal 中的 mallocByteString 创建缓冲区。

在写入时,有时我可能会意识到我没有分配足够的内存,所以我分配了一个更大的缓冲区并改用它。 这个过程(重新分配,复制,忘记旧的 ptr)可能会发生很多次。

{-# LANGUAGE TypeApplications #-}
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable
import qualified Data.ByteString.Internal as BSI


test :: IO ()
test = do
  let capacity = 1024
  foreignPtr <- BSI.mallocByteString capacity
  withForeignPtr foreignPtr $ \ptr -> do
    poke @Word8 ptr 0
    poke @Word8 (ptr `plusPtr` 1) 1
    poke @Word8 (ptr `plusPtr` 2) 2
    poke @Word8 (ptr `plusPtr` 3) 3
    -- etc

    -- oops, 1024 bytes isn't going to be enough
    foreignPtr' <- BSI.mallocByteString (capacity * 2)
    withForeignPtr foreignPtr' $ \ptr' -> do
      BSI.memcpy ptr ptr' capacity

      -- poke ptr', poke ptr', poke ptr'

我的问题是:一旦我将内容从 ptr 复制到 ptr',旧的 ptrforeignPtr 会怎样?

即使 withForeignPtr 延续仍在执行,它是否可以选择进行垃圾回收? 我需要以某种方式释放它吗?

我担心,如果我必须重新分配 10 次,我将有 9 个缓冲区占用不必要的内存。

我重组了代码,以便在缓冲区已满时退出 withForeignPtr 然后 realloc/copy over:

test2 :: IO ()
test2 = do
  let capacity = 1024
  foreignPtr <- BSI.mallocByteString capacity
  withForeignPtr foreignPtr $ \ptr -> do
    poke @Word8 ptr 0
    poke @Word8 (ptr `plusPtr` 1) 1
    poke @Word8 (ptr `plusPtr` 2) 2
    poke @Word8 (ptr `plusPtr` 3) 3
    -- etc

    -- oops, 1024 bytes isn't going to be enough
    return ()

  foreignPtr' <- BSI.mallocByteString (capacity * 2)
  withForeignPtr foreignPtr' $ \ptr' -> do
    withForeignPtr foreignPtr $ \ptr ->
      BSI.memcpy ptr ptr' capacity

    poke @Word8 (ptr' `plusPtr` capacity) 0
    poke @Word8 (ptr' `plusPtr` (capacity + 1)) 1
    poke @Word8 (ptr' `plusPtr` (capacity + 2)) 2

我相信,通过这种方式,GC 将能够清理旧指针。