使用後に明示的な解放プロセスを必要とするサブオブジェクトを持つデータ構造またはオブジェクトを初期化する場合、初期化プロセス中のエラーをどのように処理すればよいですか?
SUBOBJ1 スロットと SUBOBJ2 スロットを使用して OBJECT オブジェクトを初期化し、int 値への外部ポインターを設定する例を見てみましょう。
(defun init-object ()
(let ((obj (make-object)))
(setf (subobj1 obj) (cffi:foreign-alloc :int)
(subobj2 obj) (cffi:foreign-alloc :int))
obj))
SUBOBJ2 スロットの FOREIGN-ALLOCing でエラーが発生した場合は、SUBOBJ1 スロットの FOREIGN-FREEing を実行して、メモリ リークを回避する必要があります。
アイデアとして、私は以下のように書くことができます:
(defun init-object ()
(let ((obj (make-object)))
(handler-case
(setf (subobj1 obj) (cffi:foreign-alloc :int)
(subobj2 obj) (cffi:foreign-alloc :int))
(condition (c) ; forcedly handling all conditions
(when (subobj1 obj) (cffi:foreign-free (subobj1 obj)))
(error c))) ; invoke the condition c again explicitly
obj))
より良いアイデア、または一般的に慣用的なパターンはありますか?
ありがとう
回答に続いて、UNWIND-PROTECT を使用してコードを追加します。すべての割り当てが正常に完了した場合でも、割り当て解除フォームが実行されるため、機能しません。
(defun init-object ()
(let ((obj (make-object)))
(unwind-protect
(progn
(setf (subobj1 obj) (cffi:foreign-alloc :int)
(subobj2 obj) (cffi:foreign-alloc :int))
obj)
; foreign pointers freed even when successfully initialized
(when (subobj2 obj) (cffi:foreign-free (subobj2 obj)))
(when (subobj1 obj) (cffi:foreign-free (subobj1 obj))))))