Как правильно управлять выделенной памятью на иностранном языке?

Мой случай довольно прост: у меня есть приложение на C++ и библиотека Haskell, и мне просто нужно экспортировать из Haskell функцию, которая вернет C-строку.

Проблема в том, что строка C изначально является String, и чтобы получить из нее строку C, мне нужно выделить память, которая должна быть явно освобождена (Haskell free или finalizerFree, как документация для newCString говорит).

Какой хороший способ справиться с этим? В частности, у меня есть несколько соображений:

В идеале я хотел бы каким-то образом позволить сборщику мусора во время выполнения Haskell справиться с этим, но я не уверен, как он может узнать, когда и когда память все еще нужна сторонней стороне. Является ли это возможным?

Если нет, могу ли я просто вызвать C free или хранилище CString поддерживается средой выполнения Haskell? если нет, я полагаю, что мне придется экспортировать Haskell free и вызывать его с внешней стороны, верно?


person MasterMastic    schedule 22.01.2015    source источник
comment
CString — это просто псевдоним для голого указателя. Haskell не будет управлять своей памятью за вас. Вы можете создать ForeignPtr, если хотите, но для этого требуется некоторая забота. Каждый раз, когда вы используете указатель, он должен полностью содержаться в withForeignPtr звонок.   -  person Rufflewind    schedule 23.01.2015
comment
Если строка не слишком велика (и не видоизменяется), вам может быть лучше скопировать ее так, чтобы одна копия принадлежала внешней стороне, а другая — среде выполнения Haskell. В противном случае вы можете подумать о том, что внешняя сторона передает владение строкой Haskell, то есть внешняя сторона не сохраняет никаких ссылок на память, и если ей нужно что-то сделать, она обращается к Haskell для этого.   -  person John L    schedule 23.01.2015


Ответы (1)


Вы должны освободить строку: как вы говорите, сборщик мусора Haskell никак не может знать, нужно ли это все еще на внешней стороне.

free в Haskell точно эквивалентен free в C. Вы можете звонить с той стороны, с которой вы предпочитаете.

free :: Ptr a -> IO ()
free  = _free

foreign import ccall unsafe "stdlib.h free"    _free    :: Ptr a -> IO ()

Я не проверял, предусмотрено ли это отчетом Haskell + приложением FFI, но я думаю, что да.

person chi    schedule 22.01.2015
comment
Можно также использовать pokeArray с внешним буфером, чтобы быть в безопасности. - person Rufflewind; 23.01.2015
comment
free в Haskell точно эквивалентен free в C. Это может быть правдой, но следует соблюдать осторожность. См. blog.haskell-exists.com/yuras/posts. /malloc-free-and-ffi.html - person Elliot Cameron; 12.02.2015