While I alloc the native handle, I should free then. Or it will cause the leak.
I known the Steel Bank Common Lisp has a extend function named "finalize", it can bind a designated function to a object and let it to be called when there are no more references to object.
I think that's a good idea for mainten FFI's alloced pointer, is it? : )
So I wish newlisp may has the similar mechanism for usage.
Under is the part of the "finalize" function of SBCL's document.
— Function: finalize [sb-ext] object function &key dont-save
Arrange for the designated function to be called when there are no more references to object, including references in function itself.
If dont-save is true, the finalizer will be cancelled when save-lisp-and-die is called: this is useful for finalizers deallocating system memory, which might otherwise be called with addresses from the old image.
In a multithreaded environment function may be called in any thread. In both single and multithreaded environments function may be called in any dynamic scope: consequences are unspecified if function is not fully re-entrant.
Errors from function are handled and cause a warning to be signalled in whichever thread the function was called in.
Examples:
Code: Select all
;;; GOOD, assuming RELEASE-HANDLE is re-entrant.
(let* ((handle (get-handle))
(object (make-object handle)))
(finalize object (lambda () (release-handle handle)))
object)
;;; BAD, finalizer refers to object being finalized, causing
;;; it to be retained indefinitely!
(let* ((handle (get-handle))
(object (make-object handle)))
(finalize object
(lambda ()
(release-handle (object-handle object)))))
;;; BAD, not re-entrant!
(defvar *rec* nil)
(defun oops ()
(when *rec*
(error "recursive OOPS"))
(let ((*rec* t))
(gc))) ; or just cons enough to cause one
(progn
(finalize "oops" #'oops)
(oops)) ; GC causes re-entry to #'oops due to the finalizer
; -> ERROR, caught, WARNING signalled