Ticket #526 (closed defect: invalid)

Opened 5 years ago

Last modified 5 years ago

Weird slot-value corruption (64-bit only)

Reported by: rongarret Owned by: rme
Priority: normal Milestone:
Component: IDE Version: 1.3
Keywords: Cc:

Description

I do this:

(defclass scribble-view (ns:ns-view)
  ((path :initform (#/bezierPath ns:ns-bezier-path)))
  (:metaclass ns:+ns-object))

(defun make-scribble-window ()
  (ccl::with-autorelease-pool
   (let* ((rect (ns:make-ns-rect 0 0 300 300))
	  (w (make-instance 'ns:ns-window
			    :with-content-rect rect
			    :style-mask (logior #$NSTitledWindowMask
					       #$NSClosableWindowMask
					       #$NSMiniaturizableWindowMask
					       #$NSResizableWindowMask)
			    :backing #$NSBackingStoreBuffered
			    :defer t))
          (v (make-instance 'scribble-view)))
     (#/setTitle: w #@"Scribble")
     (#/setContentView: w v)
     (#/center w)
     (#/orderFront: w nil)
     (print (slot-value v 'path))
     v)))

(slot-value (make-scribble-window) 'path)

In 32-bit CCL this does what I would expect, namely, return an NS-BEZIER-PATH object. In 64-bit CCL it returns a bogus ObjC object. But the PRINTed value of (slot-value v 'path) is an NS-BEZIER-PATH object, so somehow the PATH slot is being corrupted between the PRINT and returning V from MAKE-SCRIBBLE-WINDOW.

Change History

comment:1 Changed 5 years ago by rongarret

Hm, this problem seems to exist in CCL32 as well, but the circumstances under which it occurs seem to be slightly different. Still trying to work out exactly what those circumstances are, but during my investigation I observed the following interesting behavior:

? p
#<NS-BEZIER-PATH  (#x3B07C20)>
? (slot-value v 'path)
#<Bogus ObjC Object #x3B07C20>

Note that these are the same object.

comment:2 Changed 5 years ago by rme

  • Owner set to rme
  • Status changed from new to assigned

You are initializing the path slot in your scribble-view instance with an autoreleased NSBezierPath. The NSBezierPath instance will be released on the next trip through the event loop.

Try changing the initform to (#/init (#/alloc ns:ns-bezier-path)) or to (make-instance 'ns:ns-bezier-path). That way, you own the object, and are responsible for releasing it. To do that, you'd implement a #/dealloc method on scribble-view:

(objc:defmethod (#/dealloc :void) ((self scribble-view))
  (#/release (slot-value self 'path)
  (call-next-method))

Also also, when you use #/setContentView: or #/addSubview:, the parent view or window will retain the new view, so you should release it. So, after (#/setContentView: w v) in make-scribble-window, you'd want to add (#/release v).

The joys of manual memory management...

 http://devworld.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

comment:3 Changed 5 years ago by rongarret

I don't understand why my bezier-path object would be released "the next time through the event loop." It was not allocated on the main thread, it was allocated in a listener thread, so it seems to me it should belong to that listener thread's autorelease pool.

comment:4 Changed 5 years ago by rongarret

(Maybe we should close this ticket and move the discussion to the mailing list?)

comment:5 Changed 5 years ago by rongarret

  • Status changed from assigned to closed
  • Resolution set to invalid

I'm an idiot. I forgot there was a call to ccl::with-autorelease-pool in make-scribble-window.

Note: See TracTickets for help on using tickets.