-2

私は最小のコードを持っており、2 つの問題がありますが、今は 1 つだけが重要です。その 1 つは、事実上ゼロのコードでメモリ リークが発生したことです。もう 1 つは、コールバック内で使用できる IORef を取得できるようにするためだけに unsafePerformIO を使用することを強制していることです (パラメーターがないため、グローバルである必要があります)。はい、そのチュートリアルからいくつかコピーしました。

(間隔は気にしないでください):

{-# LANGUAGE ExistentialQuantification,
             TemplateHaskell,
             BangPatterns,
             RecursiveDo,
             GeneralizedNewtypeDeriving,
             MagicHash #-}
module Game
( Game (..)
) where
import Entity
import Util
import GUtil
import Resources
import Control.Lens
import Control.Monad.State.Lazy
import Graphics.Rendering.OpenGL hiding (get)
import Graphics.UI.GLUT hiding (get)
import Data.IORef
import qualified System.IO.Unsafe --I'm so so sorry, it's to initialize some global references since the callbacks don't have parameters

data Game = Game
          { _root :: Entity
          , _resources :: [Resource]
          }
$(makeLenses ''Game) 

gameRef :: IORef Game
gameRef = System.IO.Unsafe.unsafePerformIO (newIORef $ (Game (Entity ENull EDataNull []) []))

main :: IO ()
main = do
    (progname, _) <- getArgsAndInitialize
    createWindow "Hello World"
    idleCallback $= doUpdateGame
    displayCallback $= display
    reshapeCallback $= Just reshape
    mainLoop
reshape s@(Size w h) = do
    viewport $= (Position 0 0, s)
    postRedisplay Nothing

display :: IO ()
display = do
    clear [ ColorBuffer ]
    flush

doUpdateGame :: Maybe (IO ())
doUpdateGame = Just $ do
                modifyIORef gameRef (snd . runState updateGame)
updateGame :: State Game ()
updateGame = do 
                return ()

この小さなコードのどこに、リークを引き起こす可能性のある問題があるのでしょうか?

4

1 に答える 1

1

グローバルな unsafe は必要ありませんIORef。部分的なアプリケーションを使用するだけです。

ラフでテストされていないコード:

idleCallback $= (doUpdateGame someLocalIORef)

...

doUpdateGame :: IORef Game -> Maybe (IO ())
doUpdateGame gameRef = Just $ modifyIORef gameRef (snd . runState updateGame)

また、それを評価することを強制しIORefているようには見えないので、おそらくスペースリークです。明確な厳密性に関する注釈が役に立たない場合は、プロファイリングを試してください。

于 2013-06-10T04:10:14.007 に答える