bracket (mallocBytes size) free
будет использовать память C о malloc
и free
, тогда как allocaBytes size
будет использовать, но под управлением сборки мусора GHCs. Это само по себе огромная разница уже, так как Ptr
из allocaBytes
может быть окружен неиспользуемой (но выделенной) памяти:
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
с меньшей вероятностью взорвется в вашем лице, но за счет того, что вы не заметите, приведет ли ваш код C-кода к повреждению памяти. Хуже того, как только вы напишете за пределами границ, возвращаемых allocaBytes
, ваш возможный развращающий другой Haskell значения молча.
Однако мы говорим здесь о неопределенном поведении. Приведенный выше код может или не может быть поврежден в вашей системе. Он может также произойти сбой в части allocaBytes
.
Если бы я был вами, я бы trace the malloc
and free
calls.
* Однажды у меня был «двойное использование свободного» ошибка в середине моей программы. Отлаживал все, переписал большую часть «плохой» рутины. К сожалению, ошибка исчезла в отладочных сборках, но повторяется в выпусках. Оказалось, что в первых десяти строках main
я случайно написал b[i - 1]
с i = 0
.
Возможно ли, что буфер переполнен в * обеих * ситуациях, и это просто, что 'mallocBytes' и' free' ловят ошибку, а другая приводит к молчанию коррупции? Похоже, что 'allocaBytes' в конечном счете использует примитив GHC' newPinnedByteArray # ', поэтому он не кажется простым вызовом' malloc'. –
Я не думаю, что буфер переполнен вообще. Теперь у меня есть тесты, которые подтверждают с помощью кодирования/декодирования и сравнения блоков данных WAVE, что привязки кодера и декодера работают правильно, а декодированные данные обратно соответствуют оригиналу. Если буфер переполнен, это, скорее всего, приведет к повреждению данных. – Mark
Не обязательно. «Неопределенное поведение», ну, не определено. Это может сработать, это также может привести к тому, что ваша кошка начнет гореть. Обратите внимание, что двойное использование 'free' обычно показывает повреждение памяти, а не обязательно второе использование' free' в этой ячейке памяти. – Zeta