初始化期间指针/外部指针的垃圾收集
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'
,旧的 ptr
和 foreignPtr
会怎样?
即使 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 将能够清理旧指针。
我正在使用 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'
,旧的 ptr
和 foreignPtr
会怎样?
即使 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 将能够清理旧指针。