10

ライブラリのドキュメントが言うようにCString、作成されたものは関数newCStringで解放する必要がありfreeます。CString作成時にメモリが必要で、リリース時にメモリ使用量が減少することを期待していましfreeたが、そうではありませんでした! コード例は次のとおりです。

module Main where

import Foreign
import Foreign.C.String
import System.IO

wait = do
  putStr "Press enter" >> hFlush stdout
  _ <- getLine
  return ()

main = do
  let s = concat $ replicate 1000000 ['0'..'9']
  cs <- newCString s
  cs `seq` wait   -- (1)

  free cs
  wait   -- (2)

プログラムが (1) で停止したとき、htopプログラムはメモリ使用量が約 410M であることを示しました - これは問題ありません。Enter キーを押すと、プログラムは行 (2) で停止しますが、dcsが実行されたにもかかわらず、メモリ使用量はまだ 410M です!free

これはどのように可能ですか?C で書かれた同様のプログラムは、本来の動作をします。ここで何が欠けていますか?

4

1 に答える 1

8

問題はfree、文字列を収集できるようになったことをガベージ コレクターに示すだけです。ただし、実際にはガベージ コレクターの実行を強制するわけではありません。CString がガベージであることを示しているだけです。ヒープ圧力ヒューリスティックに基づいて、いつ実行するかを決定するのは GC 次第です。

への呼び出しの直後に呼び出すことにより、メジャー コレクションを強制できます。これにより、メモリがすぐに 5M 程度に減少します。performGCfree

たとえば、このプログラム:

import Foreign
import Foreign.C.String
import System.IO
import System.Mem

wait = do
  putStr "Press enter" >> hFlush stdout
  _ <- getLine
  return ()

main = do
  let s = concat $ replicate 1000000 ['0'..'9']
  cs <- newCString s
  cs `seq` wait   -- (1)

  free cs
  performGC
  wait   -- (2)

次のメモリ プロファイルで期待どおりに動作します。最初の赤い点は への呼び出しでperformGCあり、すぐに文字列の割り当てを解除します。その後、プログラムは終了するまで 5M 前後でホバリングします。

ここに画像の説明を入力

于 2012-05-09T12:50:56.923 に答える