سؤال

//creates memory leak
  self.editMyObject = [[MyObject alloc] init];

//does not create memory leak
  MyObject *temp = [[MyObject alloc] init];
  self.editMyObject = temp;
  [temp release];

والسطر الأول من التعليمات البرمجية بإنشاء تسرب الذاكرة، حتى لو كنت لا [الإصدار self.editMyObject] في طريقة dealloc الفئة التي. self.editMyObject من النوع MyObject. السطر الثاني لا يتحمل أية تسرب الذاكرة. هو السطر الأول فقط غير صحيحة أو هناك طريقة لتحرير الذاكرة؟

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

المحلول

ويعتمد السلوك الصحيح على إعلانproperty editMyObject. افتراض تم delcared أنها

@property (retain) id editMyObject; //id may be replaced by a more specific type

أو

@property (copy) id editMyObject;

وبعد ذلك الاحالة عبر self.editMyObject = يحتفظ أو نسخ الكائن المعين. منذ [[MyObject alloc] init] بإرجاع كائن الاحتفاظ بها، أن لكم والمتصل تملك، لديك الاحتفاظ اضافي مثيل MyObject وبالتالي فإنه سوف تسرب ما لم يكن هناك بيان مطابقة (كما هو الحال في كتلة الثاني). أود أن أقترح عليك قراءة البرمجة إدارة الذاكرة توجيه [2].

وكتلة التعليمات البرمجية الثاني الخاص بك هو الصحيح، على افتراض الممتلكات أعلن كما هو موضح أعلاه.

وp.s. يجب عدم استخدام [self.editMyObject release] في طريقة -dealloc. يجب عليك الاتصال [editMyObject release] (على افتراض ايفار بدعمproperty يسمى editMyObject). استدعاء استرجاع (عبر self.editMyObject آمنة لليمكنهم الدخولsynthesized، ولكن إذا يعتمد على استرجاع طغت على الدولة الكائن (والتي قد لا تكون صالحة في الموقع استدعاء -dealloc أو يسبب آثارا جانبية أخرى، لديك علة عن طريق استدعاء استرجاع.

[2] قواعد الملكية كائن في الكاكاو هي في غاية البساطة: في حالة استدعاء أسلوب الذي يحتوي على alloc، أو copy في توقيعه (أو استخدام +[NSObject new] وهو ما يعادل في الأساس إلى [[NSObject alloc] init])، ثم أنت "الخاصة" الكائن الذي هو عاد ويجب تحقيق التوازن بين اكتساب للملكية مع release. في جميع الحالات الأخرى، كنت لا تملك الكائن عاد من أسلوب. إذا كنت ترغب في الاحتفاظ بها، يجب أن تأخذ ملكية مع retain، وبعد الافراج عن ملكية مع release.

نصائح أخرى

وأعلن الممتلكات الخاصة بك "الاحتفاظ" وهذا يعني أنه تم تمريرها في الكائن يتم الاحتفاظ تلقائيا.

ولأن الكائن له بالفعل عدد مرجع واحد من الوك / التهيئة هناك ثم مرجعين وأفترض إصدار واحد فقط (في المدمر الخاص بك).

وأساسا الدعوة إلى self.editMyObject يفعل حقا هذا؛

-(void) setEditMyObject:(MyObject*)obj
{
  if (editMyObject)
  {
    [editMyObject release];
    editMyObject = nil;
  }

  editMyObject = [obj retain];
}

حسب اتفاقية في الكاكاو والكاكاو تعمل باللمس، أي كائن تم إنشاؤها باستخدام [[SomeClass alloc] initX] أو [SomeClass newX] يتم إنشاؤه مع الاحتفاظ العد من واحد. أنت مسؤول عن الدعوة [someClassInstance release] عند الانتهاء من ذلك مع المثال الجديد، وعادة في طريقة dealloc الخاص بك.

وأين يحصل هذا صعب هو عند تعيين كائن جديد لخاصية بدلا من متغير مثيل. وتعرف معظم الخصائص كما retain أو copy، وهو ما يعني أنها إما زيادة الكائن الاحتفاظ العد عندما وضعت، أو تقديم نسخة من الكائن، وترك الأصل لم يمسها.

في المثال الخاص بك، ربما لديك هذا في ملف .h الخاص بك:

@property (retain) MyObject *editMyObject;

وهكذا في المثال الأول:

// (2) property setter increments retain count to 2
self.editMyObject = 

    // (1) new object created with retain count of 1
    [[MyObject alloc] init];

// oops! retain count is now 2

وعند إنشاء مثيل جديد بك من MyObject باستخدام alloc / init، ولها الاحتفاظ العد من واحد. عند تعيين مثيل جديد لself.editMyObject، وأنت تدعو في الواقع طريقة -setEditMyObject: أن يخلق مترجم لك عند @synthesize editMyObject. عندما يرى المترجم self.editMyObject = x، فإنه يستبدل مع [self setEditMyObject: x].

في المثال الثاني:

MyObject *temp = [[MyObject alloc] init];
// (1) new object created with retain count of 1

self.editMyObject = temp;
// (2) equivalent to [self setEditMyObject: temp];
// increments retain count to 2

[temp release];
// (3) decrements retain count to 1

وكنت على عقد لكائن الجديد الخاص بك لفترة كافية لتحريرها، بحيث يتم متوازنة في الاحتفاظ العد (على افتراض انك الإفراج عنها في طريقة dealloc الخاص بك).

وانظر أيضا لإدارة مؤشر / ذاكرة

والنسخة الأولى بإنشاء كائن من دون الافراج عن مطابقة. عند الوك الكائن، فهذا يعني أنك مالك هذا الكائن. اضع لكم يفترض يحتفظ الكائن (كما يجب)، وهذا يعني أنك الآن تملك الكائن مرتين. كنت في حاجة إلى إطلاق سراح لتحقيق التوازن في إنشاء الكائن.

ويجب عليك قراءة دليل إدارة الذاكرة الكاكاو إذا كنت تخطط لاستخدام الكاكاو على الإطلاق. انها ليست من الصعب مرة كنت تعلم ذلك، ولكن هذا شيء عليك أن تتعلم أو سيكون لديك الكثير من المشاكل من هذا القبيل.

وأي شخص آخر وقد غطت بالفعل لماذا يسبب تسرب الذاكرة، ولذا فإنني سوف تتناغم فقط في مع كيفية تجنب "مؤقت" متغير ومازال منع حدوث تسرب للذاكرة:

self.editMyObject = [[[MyObject alloc] init] autorelease];

وهذا سيترك الخاص بك (الاحتفاظ) الملكية باعتبارها المالك الوحيد للكائن جديد. بالضبط نفس النتيجة مثل المثال الثاني، ولكن من دون كائن مؤقت.

واتفق وأوضح أن الكود بالأسفل لايوجد تسرب (على افتراضproperty الاحتفاظ بها وsynthesize لeditMyObject):

//does not create memory leak
MyObject *temp = [[MyObject alloc] init];
self.editMyObject = tempt;
[temp release];

والسؤال: أي شيء خاطئ مع التعليمات البرمجية التالية التي لا تستخدم مؤشر درجة الحرارة

//does not create memory leak ?
self.editMyObject = [[MyObject alloc] init];
[editMyObject release];

للي هذا يبدو على ما يرام.

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