2014-11-03 2 views
22

도입어떻게 GHCI 릴리스 메모리

a 더 이상 사용하는 경우 다음 코드는, runhaskell 하스켈 가비지 콜렉터를 사용할 때하면 메모리를 해제 있음을 보여줍니다 할 수 있습니다. 변수 a을 해제하는 동안 코어 덤프가 발생합니다 - 목적을 위해 동작을 검사합니다. a은 최종 자로 nullFunPtr을가집니다.

module Main where 

import Foreign.Ptr 
import Foreign.ForeignPtr 


main :: IO() 
main = do 
    a <- newForeignPtr nullFunPtr nullPtr 
    putStrLn "Hello World" 

문제

이 메모리를 해제하지 않습니다 ghci에서 동일하게 실행. ghci가 더 이상 사용 된 변수를 해제하지 않게하려면 어떻게해야합니까?

$ ghci 
> import Foreign.Ptr 
> import Foreign.ForeignPtr 
> import System.Mem 
> a <- newForeignPtr nullFunPtr nullPtr 
> a <- return() -- rebinding variable a to show gc that I'm no longer using it 
> performGC 
> -- did not crash - GC didn't release memory 
> ^D 
Leaving GHCi. 
[1] 4396 segmentation fault (core dumped) ghci 

메모리가 종료 될 때 릴리스되었지만 너무 늦었습니다. 저는 GHCi를 확장하여 다른 용도로 사용하고 있으며, 메모리를 일찍 출시해야합니다 - 가능한 한 빨리 또는 빨리해야합니다.

나는 finalizeForeignPtr이라고 부를 수는 있지만, 디버그 목적으로 만 foreignPtr을 사용하고 있습니다. 마지막 예제에서 일반적으로 a을 어떻게 풀 수 있습니까?

ghci 프롬프트로 실행할 가능성이없는 경우 ghci 코드를 수정할 수도 있습니다. 이 aghci Interactive Context 또는 DynFlags으로 수정하여 출시 할 수 있습니까? 지금까지 나는 내 reaserch와 아무런 운이 없어. 즉 HValue의 이름에 대응 관계 우리는 값이 ClosureEnv 된 데이터 형식 PersistentLinkerState의 분야 closure_env에 저장된 것을 알게 코드를 통해 추적

+1

메모리가 해제되지 않았습니까? 변수가 GC 일 때 종료자가 즉시 실행된다는 보장이 없다고 생각합니다. –

+1

오히려 예, 나는 큰 배열로 비슷한 테스트를 수행하고 그것을'ekg'로 모니터링합니다. 아무것도 공개되지 않았다. – remdezx

+0

'()'에 재 할당 한 후 왜'a' 가비지 수집해야합니까? 어떻게 ghci가 (일종의 IO 모나드에서) 필요할 필요가 없다는 것을 알 수 있습니까? –

답변

9

. Linker.hs에서 관련 기능은

extendLinkEnv :: [(Name,HValue)] -> IO() 
-- Automatically discards shadowed bindings 
extendLinkEnv new_bindings = 
    modifyPLS_ $ \pls -> 
    let new_closure_env = extendClosureEnv (closure_env pls) new_bindings 
    in return pls{ closure_env = new_closure_env } 

과 댓글이는 그림자 바인딩을 제거해야 함을 나타냅니다 있지만, 적어도 방법 당신은 원하지 않습니다.

이유는 AndrewC가 올바르게 작성했기 때문입니다. 두 변수가 모두 동일한 소스 코드 이름을 가지고 있지만 컴파일러와 다릅니다 (다른 Unique이 붙어 있습니다). 우리는 위의 기능에 약간의 추적을 추가 한 후이를 관찰 할 수있다 : 당신의 GC 문제를 해결해야이 시점에서 동일한 소스-이름으로

*GHCiGC> a <- newForeignPtr nullFunPtr nullPtr 
extendLinkEnv [a_azp] 
*GHCiGC> a <- return() 
extendLinkEnv [a_aF0] 
*GHCiGC> performGC 
extendLinkEnv [it_aFL] 

제거 바인딩을하지만, 내가 무엇을 말할 충분히 컴파일러를 모르는 그렇지 않으면 깨질 것입니다. 나는 표를 여는 것이 좋겠다. 누군가가 알기를 바란다. 값 대 바인딩에

혼란 코멘트에서

바인딩 및 값에 대한 약간의 혼동이있을 것 같습니다.이 코드를 고려 :

> a <- return something 
> b <- return somethingelse 
> a <- return (b+b) 
> b <- return anewthing 

현재 구현을 힙은`

  • something
  • somethingelse
  • (+) 연산자와 somethingelse
  • anewthing를 참조 썽크 구성됩니다.

또한 인터프리터 환경에는 4 개의 힙 값 모두에 대한 참조가 있으므로 아무 것도 GC 할 수 없습니다. 당연히 예상 remdezx 무엇

는 GHCi가 somethingsomethingelse참조를 떨어질 것입니다. 이것은 차례로 런타임 시스템이 something을 수집하도록 허락 할 것입니다 (우리는 더 이상의 참조를 가정하지 않습니다). GHCi는 여전히 somethingelse을 참조하는 썽크를 참조하므로 이 아니기 때문에은 가비지 수집됩니다.

분명히 질문은 구현에 따라 매우 다양합니다. 따라서 대답은 :-)

+2

바인딩은 음영 처리 될 수 있지만 여전히 간접적으로 참조됩니다 :'a <- return 1; f <- return (const a); a <- return(); $ f undefined'를 출력하십시오. –

+0

시간을내어 해당 주제에 대해 자세히 알아보십시오. 이미 비슷한 버그 (https://ghc.haskell.org/trac/ghc/ticket/9765)를보고했지만 다른 보고서를보고 문제를 구분합니다. – remdezx

+2

@Will Ness : 바인딩을 더 이상 참조 할 수 없습니다. 물론 ''가치 ''는 할 수는 있지만 종단점에서 안전하게 참조 할 수 있으므로 "명명 된 사물 환경"을 유지할 필요가 없습니다! –