[Openmcl-devel] PDFKit crashes

Ron Garret ron at awun.net
Wed May 27 23:06:08 PDT 2009

Thanks!  It actually turns out that it's the pdf-view that needed to  
be initialized.

It turns out that I've been forgetting to #/init things all over the  
place but things still mostly work for me.  Am I just getting lucky?   
Should #/init always be called when #/alloc is called?  If not, how do  
you know when you need to call #/init?  (Feel free to treat those as  
rhetorical questions.  I'm sure there's a Cocoa memory management  
primer somewhere that I can go read.)

Just for the record, SCE is supposed to be P1.  The document I was  
using to test with originally was called sce.pdf (because it was a  
scanned electricity bill from Southern California Edison).  I intended  
to rename it to be more generic to avoid confusion and ended up  
creating more confusion.  Sorry about that.

Also for the record, I think calling #/description for printing is  
fine despite the potential fragility.  The extra functionality is very  
useful, and the right way IMO to make it less fragile is with a  
wrapper layer that handles all the initialization and memory management.


On May 27, 2009, at 8:13 PM, Gary Byers wrote:

> T
> On Wed, 27 May 2009, Ron Garret wrote:
>> On May 27, 2009, at 4:19 PM, Ron Garret wrote:
>>> Trying to open and display a PDF file crashes CCL in various ways.
>>> Using this code:
>>> (in-package "CL-USER")
>>> (require :cocoa)
>>> (objc:load-framework "Quartz" :quartz)
>>> (defun nsstr (s) (make-instance 'gui::ns-lisp-string :string s))
>>> (defun pdf-from-file (filename)
>>> (#/initWithData: (#/alloc ns:pdf-document)
>>>                  (#/dataWithContentsOfFile: ns:ns-data filename)))
>>> (defun pdf-from-url (url)
>>> (#/initWithUrl: (#/alloc ns:pdf-document)
>>>                 (#/URLWithString: ns:ns-url url)))
>> So it turns out that this problem is due to misspelling initWithURL  
>> as
>> initWithUrl.  Still, it would be good if the result of this were  
>> not a
>> hard crash.
> An ObjC message named #/description is applicable to all NSObjects; it
> returns an NSString which ... um, describes the object:
> ? (#/description (#/init (#/alloc ns:ns-object)))
> #<NS-MUTABLE-STRING "<NSObject: 0x12994200>" (#x12943380)>
> There isn't too much to say about a direct instance of NS:NS-OBJECT,  
> but
> for instances of other classes there's often quite a bit of  
> information
> in the #/description string.  The default PRINT-OBJECT method for  
> invokes #/description, obtains a lisp string from the ns-string, and  
> uses
> the resulting string (all of it ...) in its output.  (As I was typing
> this, I saw a message suggesting that this output observe *PRINT- 
> that isn't relevant to the printing of strings, but truncating the  
> string to some reasonable length would probably be reasonable.)
> In most cases, the existing #/description methods are remarkably  
> robust,
> but in at least some cases - most of which seem to involve objects  
> that
> have been allocated but not yet initialized - they leap before looking
> and try to print uninitialized slots in the object:
> ? (#/description (#/alloc ns::pdf-document))
> Unhandled exception 10 at 0x1451647a, context->regs at #xb029b970
> Exception occurred while executing foreign code
> at .objc_category_name_NSColor_PDFColorUtilities + 99450
> which looks kind of familiar.  So yes, you should have gotten a  
> runtime
> when trying to call a misspelled ObjC method name (which was warned  
> about)
> and in fact you did.  The system started to enter a break loop (the  
> good
> news: on the event thread in the context in which the error  
> occurred; the
> bad news: using AltConsole, until something better comes along) but  
> crashed
> trying to print the (uninitialized) NS:NS-PDF-DOCUMENT object by  
> printing
> the string returned by its #/description method.  (Look at the  
> backtrace.)
> I don't know how to tell in general whether or not it's safe to call a
> #/description method on an arbitrary NSObject (it certainly seems to
> be in the vast majority of cases, but it may be hard to recover from
> the cases where it isn't.)  Until this point, I'd been fairly
> impressed at how robust #/description methods are, but that enthusiasm
> is certainly tempered by cases like this.  At the very least, in cases
> where the output is unsolicited (error messages), it'd likely be wiser
> to not call #/description when printing an NSObject unless we're more
> sure than we can be in general that that won't sail off into the  
> ozone.
>> Still puzzling over the second problem.
> Both your earlier email message and the bug report seem to contain
> references to something named "sce", which doesn't seem to be defined
> anywhere.
> In the code that I can see, you seem to be calling #/setDocument: on
> an NS:PDF-VIEW that's been allocated but not initialized.
> Doing
> ? (allocate-instance 'some-standard-clos-class)
> returns (in the general case) an instance of the specified class where
> all of the instance's slots are unbound; that's likely not to be as
> useful an object as the result of MAKE-INSTANCE would have been.
> Similarly, the NSObject returned by a call to #/alloc on its class
> isn't yet initialized and is unlikely to behave itself; you generally
> don't want to do anything with the result of a call to #/alloc but
> immediately call some flavor of #/init... on it.)  ObjC's #/alloc
> and #/init are similar to ALLOCATE-INSTANCE and INITIALIZE-INSTANCE,
> but differ in some subtle ways (an #/init method may deallocate its
> argument and return some other instance.)  It's often saner to
> avoid this gunk and simply use MAKE-INSTANCE:
> (make-instance some-objc-class)
> is equivalent to
> (#/init (#/alloc some-objc-class)) ; all NSObjects respond to #/init
> and
> (make-instance some-objc-class :with-x x :and-y y)
> is equivalent to
> (#/initWithX:andY: (#/alloc some-objc-class) x y)
> but may be less error-prone.
>> rg
>> _______________________________________________
>> Openmcl-devel mailing list
>> Openmcl-devel at clozure.com
>> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list