سؤال

أنا أكتب إطار عمل ولدي كائن ذو طريقة init مخصصة:

@implementation OSDatabase
@synthesize database;

// MEM
- (void)dealloc {
  sqlite3_close(database);

  [super dealloc];
}

// INIT
- (id)initWithDatabasePath:(NSString *)path error:(NSError **)error {
  if (self = [super init]) {
    if (!sqlite3_open_v2([path UTF8String], &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
      error = [NSError errorWithDomain:@"OSDatabaseErrorDomain" code:1 userInfo:nil];
      [self dealloc];
      return nil;
    }
  }

  return self;
}

@end

هل من الآمن الاتصال dealloc داخل init الطريقة إذا حدث خطأ؟ لست متأكدًا من ذلك وإدارة الذاكرة هي واحدة من أهم الأشياء في حياتي.

شكرًا.

هل كانت مفيدة؟

المحلول

هل من الآمن استدعاء Dealloc داخل طريقة init إذا حدث خطأ؟

لا الإرسال -release مثلك في كل مكان آخر. حتى في -init لا يمكنك ضمان أن عدد الاحتفاظ الحالي هو 1.


لماذا يجب ألا ترسل أبدًا -dealloc إلا [super dealloc] في -dealloc؟ والسبب هو أنه لا يمكنك ضمان أن يكون هناك شيء آخر أيضًا إشارة إلى كائنك ، حتى في كائنك -init بسبب ال [super init] قد تختار الاحتفاظ بالكائن.

إذا تم إرجاع الكائن [super init] لديه عدد الاحتفاظ 1 ، إرسال -release سيكون له نفس تأثير الإرسال -dealloc. إذا كان لديه عدد أكبر من 1 ، فإن هناك شيئًا آخر يعتقد أنه يمتلك الكائن ويتركه سيتركه مع مؤشر غير صالح ، لذلك -release لا يزال الشيء الصحيح الذي يجب القيام به.

هذا ايضا:

while([self retainCount] != 0){[self release];}

من شأنه أن يؤدي إلى حلقة لا حصر لها وهي فكرة فظيعة لعدد من الأسباب. تهم الاحتفاظ بالأشياء لا تنخفض إلى 0. -release يبدو مثل هذا:

- (id)release
{
    if (retainCount == 1)
    {
        [self dealloc];
    }
    else
    {
        retainCount--;
    }
}

لذا فإن الحلقة ستقلل من العد إلى 1 ثم استدعاء Dealloc إلى الأبد أو حتى فساد الكومة الذي تسبب في يؤدي إلى خطأ SEG.

بصرف النظر عن عدم الوصول إلى الصفر ، قد يكون الاحتفاظ UINT_MAX (على سبيل المثال في الأسلاك أو الحرفية الرقمية) والتي تعني العامية "يجب ألا يتم تخصيص هذا الكائن أبدًا". إذا كان عدد الاحتفاظ UINT_MAX, -release لن يقلل من ذلك.

نصائح أخرى

لكل مستندات يجب ألا تتصل بمواجهة مباشرة - فقط - فقط [super dealloc] الطريقة في Dealloc المخصصة الخاصة بك.

أعتقد أن الدعوة release بدلاً من ذلك ، يجب أن تفعل ما هو متوقع (على الأقل إذا كنت تستخدم طريقة init فقط في نمط التخصيص القياسي).

كما ذكر فلاديمير أنك يجب ألا تتصل أبدًا dealloc مباشرة. عندما يصل عدد الكائن إلى 0 ، يتصل الكاكاو تلقائيًا dealloc.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top