Commits

Ronald Oussoren committed c334749

This is a fairly experimental check-in that seems to solve an issue with
memory managment. The patch makes sure that we release objects using the
-autorelease method instead of using -release.

The issue this solves: I have and object that contains an NSMetadataQuery
instance as an attribute. Without this patch I'd get a crash if this instance
was erased, although the query was completely finished and stopped. The
workaround: ``self.query.retain().autorelease()``, which is less than
beautiful.

Comments (0)

Files changed (6)

Examples/WebKit/PyDocURLProtocol/PyDocEvents.py

     urlfield = objc.IBOutlet('urlfield')
 
     def handleEvent_withReplyEvent_(self, event, replyEvent):
-        theURL = event.descriptorForKeyword_(
-                fourCharToInt('----'))
+        theURL = event.descriptorForKeyword_(fourCharToInt('----'))
 
         self.urlfield.setStringValue_(theURL.stringValue())
         self.webview.takeStringURLFrom_(theURL)

Lib/objc/test/test_keyvalue.py

         # Check for using KVO in python.
 
         def testAutomaticObserving(self):
+            outer_pool = NSAutoreleasePool.alloc().init()
             observer = PyObjCTestObserver.alloc().init()
             o = PyObjCTestObserved2.alloc().init()
             pool = NSAutoreleasePool.alloc().init()
 
             before = DEALLOCS
             del o
+            del outer_pool
             self.assertEquals(DEALLOCS, before+1, u"Leaking an observed object")
 
         def testObserving(self):
+            pool = NSAutoreleasePool.alloc().init()
             observer = PyObjCTestObserver.alloc().init()
 
             o = PyObjCTestObserved1.alloc().init()
 
             before = DEALLOCS
             del o
+            del pool
             self.assertEquals(DEALLOCS, before+1, u"Leaking an observed object")
 
         def testObserving2(self):

Lib/objc/test/test_leaks.py

 
         LeaksDel = 1
 
+class SlottedClass (NSObject):
+    __slots__ = ('slot1',)
+
+    def init(self):
+        self = NSObject.init(self)
+        self.slot1 = LeaksClass.alloc().init()
+        return self
+
+class MemberClass (NSObject):
+
+    def init(self):
+        self = NSObject.init(self)
+        self.slot1 = LeaksClass.alloc().init()
+        return self
+
 class TestRetains(unittest.TestCase):
     def testPyClass(self):
 
         LeaksDel = 0
         self.assertEquals(LeaksDel, 0)
 
+        pool = NSAutoreleasePool.alloc().init()
         o = LeaksClass.alloc().init()
         self.assert_(o is not None)
         self.assertEquals(LeaksDel, 0)
         del o
+        del pool
         self.assertEquals(LeaksDel, 1)
 
     def testOCClass1(self):
         del pool
         self.assertEquals(LeaksDel, 1)
 
+    def testSlots(self):
+        global LeaksDel
+
+        LeaksDel = 0
+        pool = NSAutoreleasePool.alloc().init()
+
+        o = SlottedClass.alloc().init()
+        self.assertEquals(LeaksDel, 0)
+        del o
+        del pool
+        self.assertEquals(LeaksDel, 1)
+
+    def testMembers(self):
+        global LeaksDel
+
+        LeaksDel = 0
+        pool = NSAutoreleasePool.alloc().init()
+
+        o = MemberClass.alloc().init()
+        self.assertEquals(LeaksDel, 0)
+        del o
+        del pool
+        self.assertEquals(LeaksDel, 1)
+
+
 
 if __name__ == '__main__':
     unittest.main()

Lib/objc/test/test_subclass.py

             def __del__(self):
                 aList.append('__del__')
 
+        pool = NSAutoreleasePool.alloc().init()
         del aList[:]
         o = ClassWithRetaining.alloc().init()
         v = o.retainCount()
         self.assertEquals(aList, ['retain', 'release'])
         self.assertEquals(o.retainCount(), v)
         del o
+        del pool
 
         self.assertEquals(aList, ['retain', 'release', 'release', '__del__'])
 
         
         self.assertEquals(aList, ['retain', 'release', 'release', '__del__'])
 
+        pool = NSAutoreleasePool.alloc().init()
         class ClassWithRetainCount(NSObject):
             def retainCount(self):
                 aList.append('retainCount')
         self.assert_(isinstance(v, int))
         self.assertEquals(aList, ['retainCount'])
         del o
+        del pool
 
     def testOverrideDealloc(self):
         aList = []
                 return super(ClassWithDealloc, self).dealloc()
 
         del aList[:]
+        pool = NSAutoreleasePool.alloc().init()
         o = ClassWithDealloc.alloc().init()
         self.assertEquals(aList, [])
         del o
+        del pool
         self.assertEquals(len(aList), 2)
         self.assert_('dealloc' in aList)
         self.assert_('__del__' in aList)
                 return super(SubClassWithDealloc, self).dealloc()
 
         del aList[:]
+        pool = NSAutoreleasePool.alloc().init()
         o = SubClassWithDealloc.alloc().init()
         self.assertEquals(aList, [])
         del o
+        del pool
         self.assertEquals(len(aList), 3)
         self.assert_('dealloc.dealloc' in aList)
         self.assert_('dealloc' in aList)
                 aList.append('mydel')
 
         del aList[:]
+        pool = NSAutoreleasePool.alloc().init()
         o = ClassWithDeallocAndDel.alloc().init()
         self.assertEquals(aList, [])
         del o
+        del pool
         self.assertEquals(len(aList), 3)
         self.assert_('mydel' in aList)
         self.assert_('dealloc' in aList)

Modules/objc/objc-object.m

 			 *   clusters like NSArray.
 			 */
 			char buf[256];
-
 			snprintf(buf, sizeof(buf), 
 				"leaking an uninitialized object of type %s",
 				obj->ob_type->tp_name);
 			((PyObjCObject*)obj)->objc_object = nil;
 		} else {
 			PyObjC_DURING
-				[((PyObjCObject*)obj)->objc_object release];
+				if (strcmp(GETISA(((PyObjCObject*)obj)->objc_object)->name, 
+						"NSAutoreleasePool") != 0) {
+
+					[((PyObjCObject*)obj)->objc_object autorelease];
+				} else {
+					[((PyObjCObject*)obj)->objc_object release];
+				}
 
 			PyObjC_HANDLER
 				NSLog(@"PyObjC: Exception during dealloc of proxy: %@",
 
 An overview of the relevant changes in new, and older, releases.
 
+Version 1.3.8 (????-??-??)
+
+- Make it possible to override the KVO methods, like ``setValue:forKey:`` and
+  ``valueForKey:`` in Python for all levels in the inheritance hierarchie.
+
+- Fix issues with reference counts for ``__slots__``.
+
+- Experimental: use ``-autorelease`` instead of ``-release`` to release
+  values in destructors. This seems to solve at least one memory managment
+  issue.
+
+
 Version 1.3.7 (2005-07-06)
 --------------------------