shuiyouren / sqlitepersistentobjects

Automatically exported from code.google.com/p/sqlitepersistentobjects
0 stars 0 forks source link

Show error when trying to release a sqlite persistent object #83

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. create a sample class extends SQLitePersistentObject like below:
#import <Foundation/Foundation.h>
#import "SQLitePersistentObject.h"

@interface Post : SQLitePersistentObject {
    NSString *title;
    NSString *text;
    NSString *transientBit;
}
@property (nonatomic,readwrite,retain) NSString *title;
@property (nonatomic,readwrite,retain) NSString *text;
@property (nonatomic,readwrite,retain) NSString *transientBit;

@end;
#include "Post.h"

@implementation Post

@synthesize title, text, transientBit;

- (void)dealloc
{
    [title release];
    [text release];
    [super dealloc];
}

@end

2. alloc/init it in .m file.

//init NSAutoreleasePool
//init SQLiteInstanceManager
Post *p = [[Post alloc] init];
//Your code
[p release];
[pool release];
return

3. Build & Run

What is the expected output? What do you see instead?
As Sample says, it should run without any issue. But it show error like this:

2010-03-26 23:08:59.478 SQLitePDDemo[5608:a0f] An instance 0x10010db60 of
class Post was deallocated while key value observers were still registered
with it. Observation info was leaked, and may even become mistakenly
attached to some other object. Set a breakpoint on NSKVODeallocateBreak to
stop here in the debugger. Here's the current observation info:

<NSKeyValueObservationInfo 0x100106e70> (

<NSKeyValueObservance 0x10010ee70: Observer: 0x10010db60, Key path: title,
Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x1001051d0>

......

What version of the product are you using? On what operating system?
sqlitepersistentobjects_02_26_2009_snapshot.zip      February 26, 2009 Snapshot 
Mac OS X Version 10.6.2

Please provide any additional information below.
My fixing:
modify SQLitePersistentObject.m 

-(void)dealloc
{
for (NSString *oneProp in [[self class] propertiesWithEncodedTypes])
{
    [self removeObserver:self forKeyPath:oneProp];
}
// original codes
}

I'm not sure if it is right, if not, please correct me. Thanks ^_^

Original issue reported on code.google.com by wilsonli...@gmail.com on 27 Mar 2010 at 3:51

GoogleCodeExporter commented 8 years ago
btw, same issue when call autorelease after init. 

Original comment by wilsonli...@gmail.com on 27 Mar 2010 at 4:03

GoogleCodeExporter commented 8 years ago
Checed it again. This issue only happens on OS X system, not iPhone.

Original comment by wilsonli...@gmail.com on 29 Mar 2010 at 2:50

GoogleCodeExporter commented 8 years ago
Checed it again. This issue only happens on OS X system, not iPhone.

Original comment by wilsonli...@gmail.com on 29 Mar 2010 at 2:50

GoogleCodeExporter commented 8 years ago
I'm seeing this issue on the iPhone w/ the latest  (pre-release) version of 
iPhone SDK.

Original comment by trevor.r...@gmail.com on 21 Jun 2010 at 12:48

GoogleCodeExporter commented 8 years ago
Also seeing this in the test cases in running against 3.2 and 4.0 sdk's

Original comment by KingSqui...@gmail.com on 5 Jul 2010 at 12:06

GoogleCodeExporter commented 8 years ago
Also saw this while debugging on iPhone 3GS / iOS4, when calling +clearCache.
wilsonli.cn's fixing is working fine for me.

SQLitePersistentObject is setting itself as its observer in -(void)init.
http://code.google.com/p/sqlitepersistentobjects/source/browse/trunk/src/SQLiteP
ersistentObject.m#1310

So I think it is natural to do removeObserver in dealloc.
I haven't found official Apple doc that removing observers is necessary before 
releasing, but here's a
stackoverflow thread that says so:
http://stackoverflow.com/questions/13927/in-cocoa-do-i-need-to-remove-an-object-
from-receiving-kvo-notifications-when-deal

Original comment by kenji.ta...@gmail.com on 7 Jul 2010 at 2:01

GoogleCodeExporter commented 8 years ago
I've fixed most of this crazy logging by doing this:

diff --git a/Lib/sqlpo/SQLitePersistentObject.m 
b/Lib/sqlpo/SQLitePersistentObject.m
index 41d5c1b..5c6c264 100644
--- a/Lib/sqlpo/SQLitePersistentObject.m
+++ b/Lib/sqlpo/SQLitePersistentObject.m
@@ -219,7 +219,7 @@ NSMutableArray *checkedTables;
 +(SQLitePersistentObject *)findByPK:(int)inPk
 {
   SQLitePersistentObject *ret = nil;
-  NSString *k = [SQLitePersistentObject memoryMapKeyForObject:inPk];
+  NSString *k = [[self class] memoryMapKeyForObject:inPk];
   if ([[objectMap allKeys] containsObject:k])
     ret = [objectMap objectForKey:k];
   if (ret == nil)
@@ -249,16 +249,14 @@ NSMutableArray *checkedTables;
     while (sqlite3_step(statement) == SQLITE_ROW)
     {
       BOOL foundInMemory = NO;
-      id oneItem = [[[self class] alloc] init];
+      int thePk = sqlite3_column_int(statement, 0);
+      NSString *mapKey = [[self class] memoryMapKeyForObject:thePk];

-      [oneItem setPk:sqlite3_column_int(statement, 0)];
-      NSString *mapKey = [oneItem memoryMapKey];
       if ([[objectMap allKeys] containsObject:mapKey])
       {
         SQLitePersistentObject *testObject = [objectMap objectForKey:mapKey];
         if (testObject != nil)
         {
-          [oneItem release];
           [ret addObject: [testObject retain] ];
           foundInMemory = YES;
         }
@@ -267,6 +265,9 @@ NSMutableArray *checkedTables;
       if(foundInMemory)
         continue;

+      id oneItem = [[[self class] alloc] init];
+      [oneItem setPk:thePk];
+      

where memoryMapKeyForObject is:

+ (NSString *)memoryMapKeyForObject:(NSInteger)thePK
{
  return [NSString stringWithFormat:@"%@-%d", [self className], thePK];
}

---

The way the code was setup before would cause crashes on faster systems when 
calling removeObserver:forKeyPath: in dealloc (this is not a good idea in 
general).

Original comment by samuraib...@gmail.com on 10 Jul 2010 at 12:09

GoogleCodeExporter commented 8 years ago
It's also a good performance improvement. :)

Original comment by samuraib...@gmail.com on 10 Jul 2010 at 4:05

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
@samurai Hey I had the same problem and your solution works perfectly thank you!

Original comment by spsriram...@gmail.com on 21 Jan 2011 at 11:50

GoogleCodeExporter commented 8 years ago
I have the same problem too! How do I apply that patch?

Original comment by tom.van....@gmail.com on 23 Jan 2011 at 1:16

GoogleCodeExporter commented 8 years ago
Happens in iOS 5 beta 6 for me.

Original comment by turfla...@gmail.com on 1 Sep 2011 at 12:01