我正在使用mallocByteString
中的Data.ByteString.Internal
创建缓冲区。
并且在写它时,有时我可能意识到我没有分配足够的内存,所以我分配了更大的缓冲区并改为使用它。此过程(重新分配,复制,忘记旧的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'
,旧的ptr
和foreignPtr
会怎样?
即使withForeignPtr
延续仍在执行,它仍可用于垃圾回收吗?我需要以某种方式释放它吗?
我担心,如果必须重新分配10次,我将有9个缓冲区占用不必要的内存。
我已经重组了代码,以便当缓冲区已满时我退出withForeignPtr
。然后重新分配/复制到:
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将能够清理旧指针。