تسرب الذاكرة باستخدام [NSKeyedUnarchiver decodeObjectForKey]

StackOverflow https://stackoverflow.com/questions/169034

  •  05-07-2019
  •  | 
  •  

سؤال

في كل مرة أقوم فيها باستدعاء هذه الطريقة، تتسرب بيانات NSMutableData الخاصة بي ولا أستطيع معرفة كيفية توصيلها.يتم زيادة عدد الاحتفاظ بالبيانات بمقدار واحد بعد تخصيص وحدة فك التشفير وتهيئتها وليس لدي أي فكرة عن السبب.أنا عالق في عدد الاحتفاظ 2 في نهاية الطريقة ومحاولة تحريره تؤدي إلى تعطل التطبيق.

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;


    theData = [NSData dataWithContentsOfFile:inFile];

    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

    venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

    [decoder finishDecoding];

    [decoder release];
}
هل كانت مفيدة؟

المحلول

أقترح استبدال هذا السطر:

venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

مع:

ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;

وهذا يجعل إدارة الذاكرة decodedList واضح.يعتبر من أفضل الممارسات تعيين متغيرات الحالة باستخدام طريقة الوصول (باستثناء طرق init).في تطبيقك الحالي، إذا قمت باستدعاء readVenueArchiveFile: للمرة الثانية على نفس الكائن، أنت سوف تسرب (كما ستفعل إذا decodedList لديها بالفعل قيمة).علاوة على ذلك، يمكنك وضع منطق النسخ في طريقة الوصول الخاصة بك ونسيانه بدلاً من الاضطرار إلى تذكر نسخة قابلة للتغيير في كل مرة تقوم فيها بتعيين قيمة جديدة (بافتراض وجود سبب وجيه لإنشاء نسخة قابلة للتغيير على أي حال؟).

نصائح أخرى

تقليل البصمة الذاكرة الذروة

بشكل عام، يعتبر من أفضل الممارسات تجنب إنشاء كائنات تم إصدارها تلقائيًا.

[تم تعديل معظم هذه الفقرة من هذا السؤال.] نظرًا لأنك عادةً(1) لا تملك تحكمًا مباشرًا في عمرها الافتراضي، يمكن أن تستمر الكائنات التي تم إصدارها تلقائيًا لفترة طويلة نسبيًا وتزيد بشكل غير ضروري من مساحة ذاكرة التطبيق الخاص بك.بينما على سطح المكتب هذا يمكن قد تكون هذه مشكلة كبيرة في الأنظمة الأساسية الأكثر تقييدًا.لذلك، في جميع الأنظمة الأساسية، وخاصة على الأنظمة الأساسية الأكثر تقييدًا، حيثما أمكن، لا ننصحك بشدة باستخدام الأساليب التي من شأنها أن تؤدي إلى كائنات تم إصدارها تلقائيًا وبدلاً من ذلك يتم تشجيعك على استخدام نمط التخصيص/التهيئة.

أود أن أقترح استبدال هذا:

theData = [NSData dataWithContentsOfFile:inFile];

مع:

theData = [[NSData alloc] initWithContentsOfFile:inFile];

ثم في نهاية الطريقة أضف:

[theData release];

هذا يعني ذاك theData سيتم إلغاء تخصيصها قبل خروج الطريقة.يجب أن ينتهي بك الأمر مع:

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;

    theData = [[NSData alloc] initWithContentsOfFile:inFile];
    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
    ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
    self.venueIOList = decodedList;
    [decoder finishDecoding];
    [decoder release];
    [theData release];

}

وهذا يجعل دلالات إدارة الذاكرة واضحة، ويستعيد الذاكرة في أسرع وقت ممكن.

(1) يمكنك التحكم باستخدام مجموعات الإصدار التلقائي المحلية الخاصة بك.للمزيد عن هذا، راجع دليل برمجة إدارة الذاكرة من Apple.

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

لتوسيع في جوابي قليلا: إن unarchiver يمكن الاحتفاظ البيانات الخاصة بك أثناء العملية من الأرشيف، وبعد ذلك بإرسال -autorelease البيانات عندما يكون القيام به بدلا من -release. ومنذ ذلك ليس شيئا <م> أنت فعلت ذلك، انها ليست شيئا <م> أنت يجب أن تهتم بها.

المصدر النهائي للتنوير إدارة الذاكرة المرتبط refcount لا يزال، IMO، "عقد لي، استخدام البيانات، حرر لي " من المتعدد المرحلي.

وكود الخاص بك هو الصحيح. لا يوجد أي تسرب للذاكرة.

theData = [NSData dataWithContentsOfFile:inFile];

وما يعادل

theData = [[[NSData alloc] initWithContentsOfFile:inFile] autorelease];

وعند هذه النقطة theData لديه عدد مرجع 1 (إذا كان أقل من ذلك، من شأنه أن يمكن deallocated ذلك). سيتم decremented عدد مرجع تلقائيا في مرحلة ما في المستقبل من قبل تجمع autorelease.

decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

والكائن فك يحتفظ إشارة إلى theData التي الزيادات عدد إشارته إلى 2.

وبعد إرجاع الأسلوب، تجمع autorelease تقليلها هذه القيمة إلى 1. إذا كنت الافراج theData في نهاية هذا الأسلوب، وعدد مرجع سيصبح 0، ويمكن deallocated الكائن، وسوف التطبيق تحطم عند محاولة استخدامها.

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