bracket (mallocBytes size) free
सी malloc
और free
, जबकि allocaBytes size
का उपयोग करेगा स्मृति कि GHCs कचरा संग्रहण द्वारा प्रबंधित का प्रयोग करेंगे। अपने आप में यही है, पहले से ही एक बड़ा अंतर है के बाद से allocaBytes
की Ptr
अप्रयुक्त (लेकिन आवंटित) स्मृति से घिरा हो सकता है:
import Control.Exception
import Control.Monad (forM_)
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
-- Write a value at an invalid pointer location
hammer :: Ptr Int -> IO()
hammer ptr = pokeElemOff ptr (-1) 0 >> putStrLn "hammered"
main :: IO()
main = do
putStrLn "Hammer time! Alloca!"
forM_ [1..10] $ \n ->
print n >> allocaBytes 10 hammer
putStrLn "Hammer time! Bracket"
forM_ [1..10] $ \n ->
print n >> bracket (mallocBytes 10) free hammer
परिणाम:
Hammer time! Alloca!
1
hammered
2
hammered
3
hammered
4
hammered
5
hammered
6
hammered
7
hammered
8
hammered
9
hammered
10
hammered
Hammer time! Bracket
1
hammered
<program crashes>
आप देख सकते हैं, हालांकि हम है arr[-1] = 0
, allocaBytes
ने उस त्रुटि को खुशी से अनदेखा किया। हालांकि, free
यदि आप -1
पर स्थिति लिखते हैं तो आपके चेहरे में अक्सर उड़ जाएगा (अक्सर)। अगर किसी अन्य आवंटित स्मृति क्षेत्र * पर स्मृति भ्रष्टाचार हो तो यह आपके चेहरे पर भी उड़ाएगा।
इसके अलावा, allocaBytes
के साथ, यह संभावना है कि पॉइंटर कहीं पहले से आवंटित स्मृति में इंगित करता है, न कि किसी की शुरुआत के लिए, उदा।
nursery = malloc(NURSERY_SIZE);
// ...
pointer_for_user = nursery + 180;
// pointer_for_user[-1] = 0 is not as
// much as a problem, since it doesn't yield undefined behaviour
इसका क्या अर्थ है? खैर, allocaBytes
आपके चेहरे पर उड़ने की संभावना कम है, लेकिन लागत पर आपको यह नहीं पता कि आपका सी-कोड संस्करण स्मृति भ्रष्टाचार का कारण बन जाएगा या नहीं। इससे भी बदतर, जैसे ही आप allocaBytes
द्वारा लौटे गए सीमाओं के बाहर लिखते हैं, तो संभवतः आप अन्य Haskell चुपचाप मानते हैं।
हालांकि, हम यहां अपरिभाषित व्यवहार के बारे में बात कर रहे हैं। उपरोक्त कोड आपके सिस्टम पर क्रैश हो सकता है या नहीं। यह allocaBytes
भाग में भी क्रैश हो सकता है।
यदि मैं आप थे, तो मैं trace the malloc
and free
calls होगा।
* मैं एक बार मेरे प्रोग्राम के बीच में त्रुटि एक "मुक्त के दोहरे उपयोग" था। सब कुछ डीबग किया, अधिकांश "खराब" दिनचर्या को फिर से लिखें। दुर्भाग्यवश, डीबग बिल्ड में गायब हो गई त्रुटि, लेकिन रिलीज बिल्ड में पुनरावृत्ति हुई। यह पता चला कि main
की पहली दस पंक्तियों में, मैंने b[i - 1]
को i = 0
के साथ गलती से लिखा था।
क्या यह संभव है कि बफर * दोनों स्थितियों में ओवरराउन हो रहा है, और यह सिर्फ 'mallocBytes' और' free' त्रुटि को पकड़ता है जबकि दूसरा चुप भ्रष्टाचार की ओर जाता है? ऐसा प्रतीत होता है कि 'एलोकाबाइट्स' अंततः जीएचसी आदिम 'newPinnedByteArray # 'का उपयोग करता है, इसलिए यह एक साधारण' मॉलोक 'कॉल प्रतीत नहीं होता है। –
मुझे नहीं लगता कि बफर बिल्कुल खत्म हो रहा है। मेरे पास अब परीक्षण हैं जो एन्कोडिंग/डिकोडिंग के माध्यम से पुष्टि करते हैं और WAVE डेटा ब्लॉक की तुलना करते हैं जो एन्कोडर और डिकोडर बाइंडिंग सही ढंग से काम करते हैं और डेटा को डीकोड किए गए डेटा को मूल से मेल खाते हैं। यदि बफर खत्म हो गया था, तो यह संभवतः डेटा भ्रष्टाचार का कारण बन जाएगा। – Mark
जरूरी नहीं है। "अपरिभाषित व्यवहार", ठीक है, अपरिभाषित है। यह काम कर सकता है, यह आपकी बिल्ली को आग लगा सकता है। ध्यान दें कि 'फ्री' का एक डबल उपयोग आमतौर पर मेमोरी भ्रष्टाचार दिखाता है, न कि उस स्मृति स्थान पर 'फ्री' का वास्तविक दूसरा उपयोग। – Zeta