When initializing a data structure, or object, which has sub objects requiring explicit release process after used, how should I handle an error during the initialization process?
Let me take an example, initializing an OBJECT object with SUBOBJ1 and SUBOBJ2 slots to be set foreign pointers to int values:
(defun init-object ()
(let ((obj (make-object)))
(setf (subobj1 obj) (cffi:foreign-alloc :int)
(subobj2 obj) (cffi:foreign-alloc :int))
obj))
If we had an error in FOREIGN-ALLOCing for SUBOBJ2 slot, we should do FOREIGN-FREEing for SUBOBJ1 slot to avoid memory leaking.
As an idea, I can write as below:
(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))
Do you have any better idea, or generally idiomatic pattern?
Thanks
Following the answers, I add a code using UNWIND-PROTECT. It would not work because the deallocating forms run even if all allocation are completed successfully.
(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))))))
Use UNWIND-PROTECT. When the error causes an exit out of the scope, unwind-protect
allows you to force the execution of clean-up forms.
Something like this:
(defun init-object ()
(let ((obj (make-object)))
(unwind-protect
(setf (subobj1 obj) (cffi:foreign-alloc :int)
(subobj2 obj) (cffi:foreign-alloc :int))
(unless (and (subobj2 obj) (subobj1 obj))
(when (subobj1 obj) (cffi:foreign-free (subobj1 obj)))
(when (subobj2 obj) (cffi:foreign-free (subobj2 obj)))))
obj))
Use whatever is available to detect if a slot is bound or not. Above assumes that a non-initialized slot has a value of NIL
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With