Сборка мусора указателей / сторонних указателей во время инициализации - PullRequest
1 голос
/ 13 февраля 2020

Я создаю буфер, используя mallocByteString из Data.ByteString.Internal.

И во время записи в него, в какой-то момент я могу понять, что не выделил достаточно памяти, поэтому я выделяю больший буфер и используйте это вместо этого. Этот процесс (reallo c, копирование, забытие о старом 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 все еще выполняется? Мне нужно как-нибудь освободить его?

Я боюсь, что, если мне придется перезаписать c 10 раз, у меня будет 9 буферов, занимающих ненужную память.

1 Ответ

0 голосов
/ 13 февраля 2020

Я реструктурировал код так, чтобы я возвращался из 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

Я полагаю, таким образом , G C сможет убирать старые указатели.

...