初始化数据结构或对象时,如果子对象使用后需要显式释放过程,初始化过程中出现错误应该如何处理?
让我举个例子,用 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))))))