2013-09-01 37 views
8

'daki bir listenin hafıza adresi nasıl yazdırılır Bazı programlama dillerinin yapılandırılmış verilere belleği nasıl atayacağını inceliyorum (bu durumda diziler üzerinde çalışıyorum).Haskell

Array Start: <dec addr> | <hex addr> --Shows where the array itself is 
Array 1: <dec addr> | <hex addr> --Memory address of the first element 
Array 2: <dec addr> | <hex addr| --Memory address of the second element 

:

bölüm 3.

import Data.Array.IO 
arr <- newArray (1,10) 37 :: IO (IOArray Int Int) --Sets default to 37 

Ve ne ben yapmaya çalışıyorum üzerinde here gösterildiği gibi dizi yaratıyorum baskı ve öğelerin her birinin bellek adresi, bir şey böyledir Sahip olduğum problem Haskell'deki bir elemanın hafıza adresi değerini nasıl alacağımı bilmem.

Python'un id(object) veya Ruby'nin object.object_id benzeri bir işlevi var mı? Bu öncelikle bir Ptr' kurucu içinde a sarılması ve daha sonra Ptr' a döküm çalışır

{-# LANGUAGE MagicHash, BangPatterns #-} 

import GHC.Exts 

-- A datatype that has the same layout as Word and so can be casted to it. 
data Ptr' a = Ptr' a 

-- Any is a type to which any type can be safely unsafeCoerced to. 
aToWord# :: Any -> Word# 
aToWord# a = let !mb = Ptr' a in case unsafeCoerce# mb :: Word of W# addr -> addr 

unsafeAddr :: a -> Int 
unsafeAddr a = I# (word2Int# (aToWord# (unsafeCoerce# a))) 

:

+3

bunun mümkün olup olmadığından emin değilim, ama sorun olduğu takdirde bellek adresi sebebiyle çöp toplayıcı tarafından tehcir istediğiniz zaman değiştirebilirsiniz. –

+0

Evet, ancak sadece belirli bir zamanda bellek adresini yazdırmak istiyorum, bu nedenle daha sonra yürütme –

+0

içinde bir 'reallyUnsafePtrEquals' var ise, 'gerçektenUnsafe' değişikliklerin GHC'nin bu kadar büyüyü açığa çıkaracağından şüphelenir. – jozefg

cevap

10

Ne ghc-heap-view paketinden ödünç aşağıdaki pasajı kullanabilirsiniz (aynı zamanda foreign import prim kullanarak alternatif bir çözüm içerir) Word. a alanı bir işaretçi olarak gösterildiğinden, sonuç sözcüğü artık nesnenin adresini içerir. Her zamanki uyarılar geçerlidir: Bu, güvensiz GHC özeldir referans şeffaflık kırar, vb

Test:

main :: IO() 
main = do 
    arr <- newListArray (1,10) [1,2..] :: IO (IOArray Int Int) 
    a1 <- readArray arr 1 
    a2 <- readArray arr 2 
    a1' <- readArray arr 1 

    putStrLn $ "a1 : " ++ (show . unsafeAddr $! a1) 
    putStrLn $ "a1 : " ++ (show . unsafeAddr $! a1) 
    putStrLn $ "a2 : " ++ (show . unsafeAddr $! a2) 
    putStrLn $ "a2 : " ++ (show . unsafeAddr $! a2) 
    putStrLn $ "a1': " ++ (show . unsafeAddr $! a1') 

Çıktı: Eğer $! ile unsafeAddr kullanmalıdır

a1 : 16785657 
a1 : 16785657 
a2 : 16785709 
a2 : 16785709 
a1': 16785657 

Not aksi halde a nesnesi yerine a değerini değerlendirecek bir thunk adresi alırsınız:

let a = 1 
     b = 2 
     c = a + b 

    putStrLn $ "c: " ++ (show . unsafeAddr $ c) 
    putStrLn $ "c: " ++ (show . unsafeAddr $! c) 
    putStrLn $ "c: " ++ (show . unsafeAddr $! c) 

Çıktı:

c: 9465024 
c: 9467001 
c: 9467001 
+1

Temiz bir fikir! Olası iyileştirmeler: Word, Int'ten daha iyi bir final tipi olacaktır (genellikle negatif olmayan adresleri düşünürüz).Eğer bunu paketleyecek olsaydınız, muhtemelen adresi kontrol etmeden önce 'a' kelimesini bir versiyon yapmak isteyebilirsiniz. –

+1

İşaretçi etiketleri burada da yazdırılıyor, maskelenmeleri gerekiyor. –

+0

@NathanHowell Haskell'de bunu yapmak sorun yaratır çünkü etiket genişliği platforma bağlıdır. “ghc-heap-view”, bu sebepten ötürü “aToWord” 'u uygular. –