The following information about MacPtrs (and specifically, dead MacPtrs) was posted by Gary Byers to openmcl-devel this morning. Since this info is generally useful, I’m putting it up in a blog entry. I’m also taking the occasion to inaugurate a new blog entry category: GB’s Greatest Hits.
In general, a pointer (to some foreign address) is only meaningful within a session;
save-application walks memory, changing the type of any non-NULL pointers it finds to
dead-macptr. Most operations on pointers do typechecking, so attempting to access something leftover from the previous session gets a type error (rather than acessing a foreign address that’s leftover from the previous session.) The exception for NULL pointers is somewhat arbitrary; it’d be just as reasonable to decide that something pointing to a “small” address (for some value of “small”) isn’t really a pointer “to” anything.
(defvar *some-foreign-pointer* (#_malloc 1000))
(defun read-into-foreign-pointer (fd)
(#_read fd *some-foreign-pointer* 1000))
;;; run the new image
will signal a
save-application has marked the value of
*some-foreign-pointer* as being dead.)
In a very simple case like this (where the pointer’s only accessible via a special variable), it’s possible to use
(ccl:defloadvar *some-foreign-pointer* (#_malloc 1000))
That’ll behave like
defstatic (which -is- documented …), but will additionally push (a compiled version of) the initform on a list of pointer-reinitialization functions that’s run when an image starts up. Entries on this list are run in the order in which they’re defined, so:
(ccl:defloadvar *a* (something))
(ccl:defloadvar *b* (something-that-depends-on *a*))
will do the (re)initialization in the same order that the initialization is done.
That’s often adequate. There are some other mechanisms (it’s possible to destructively change a
dead-macptr back into a
macptr in cases where EQness matters, and it’s possible to run arbitrary code at image startup time.)