Overficive-C البسيط-الإفراط في الإفراج عن * يجب أن * يجب أن يتحطم. لماذا ا؟

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

سؤال

إما أن تصحيح الأخطاء الخاص بي مكسور أو هناك شيء أساسي لا أفهمه.

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

int main (int argc, const char * argv[])
{
    NSString *string = [[NSString alloc] initWithString:@"Hello"];

    [string release];

    NSLog(@"Length: %d", [string length]);

    return 0;
}

يطبع عبارة السجل "الطول: 5" كما تتوقع لسلسلة صالحة. ومع ذلك ، يجب تعامل السلسلة بحلول تلك النقطة و exec_bad_access يجب إلقاء الخطأ.

لقد جربت هذا الرمز مع مرفق الأخطاء ودون مرفق التصحيح - كلاهما يعطي نفس النتيجة. لقد قمت أيضًا بتمكين (وتعطيل) NSZombie, ، الذي يبدو أنه ليس له أي تأثير (اعتقدت في البداية أن هذه هي المشكلة منذ ذلك الحين NSZombie لا يتم تعامل الكائنات أبدًا - لكنها لا تزال لا تتعطل NSZombie معاق).

لدي نقاط توقف في بلدي المحلي .gdbinit ملف لكسر أشياء مثل -[NSException raise] و objc_exception_throw. لدي أيضًا نقاط توقف على العديد من الطرق NSZombie من أجل التقاطهم.

fb -[NSException raise]
fb -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]
fb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]

#define NSZombies
# this will give you help messages.  Set to NO to turn them off.
set env MallocHelp=YES
# might also be set in launch arguments.
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1

set env CFZombie 5

fb -[_NSZombie init]
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie autorelease]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie forwardInvocation:]
fb -[_NSZombie class]
fb -[_NSZombie dealloc]

fb szone_error
fb objc_exception_throw

مع مجموعة نقاط التوقف هذه وتمكين NSZombie ، يجب أن أحصل على شيء مثل [NSString length]: message sent to deallocated instance 0x100010d39 طبعت إلى وحدة التحكم ، لكنني لا أرى هذا. أرى ال NSLog طباعة الطول على أنها 5.

أرى سلوكًا مشابهًا مع فصول أخرى مثل NSURL و NSNumber. لكن بعض الفصول تعطل كما هو متوقع ، مثل NSError و NSObject.

هل هذا له علاقة بمجموعات الفصل؟ ألا يتبعون نفس القواعد فيما يتعلق بإدارة الذاكرة؟

إذا لم تكن مجموعات الفصل مرتبطة بهذه المشكلة ، فإن الميزة الشائعة الوحيدة التي يمكن أن أراه هي أن الفصول التي لا تصطدم بهذه الطريقة كلها مجردة مع نظير الأساس الأساسي. وهل من الممكن أن تفعل شيئا بحيال ذلك؟

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

المحلول

retain/release هو عقد بين واجهة برمجة التطبيقات والمبرمج أنه عندما تتبع القاعدة ، فإنه لا يعطل. لا يضمن العقد أنه إذا لم تتبع القاعدة ، فإنه ينهار!

في هذه الحالة،

[[NSString alloc] initWithString:@"Hello"]

مجرد إرجاع نفس الكائن مثل @"Hello" كتحسين. ثابت NSString لا يتم تعامله أبدًا ؛ كتحسين ، retain و release (على ما أظن) تجاهل. لهذا السبب لا يعطل.

يمكنك التحقق من تخميني من خلال مقارنة قيمة مؤشر @"Hello" و string.

نصائح أخرى

هذا مثال ممتاز على سبب الاحتفاظ بالتعدادات هي أداة تصحيح غير مجدية. من الخطأ أن نفترض -Rectain و -easease دائمًا إضافة أو إزالة 1 من عدد الاحتفاظ وأن العد الاحتفاظ هو ما تعتقد أنه ينبغي أن يكون.

محاولة

NSString *string = [[NSString alloc] initWithFormat:@"Hello %d", argc];

يجب أن يمنحك هذا سلسلة من شأنها أن تتصرف أكثر مثل الطريقة التي تتوقعها لأنك لا تقوم بتهيئة سلسلة من ثابت وقت الترجمة. ومع ذلك ، يتم تحذيرها ، مع تمكين الزومبي ، ستحصل على السلوك الذي تتوقعه ولكن بدون الزومبي ، قد يعمل NSLog جيدًا. على الرغم من أن السلسلة قد تم تعويضها ، إلا أن البيانات الموجودة في الكائن لا تزال موجودة في الذاكرة تاركة "شبحًا" يستجيب بشكل صحيح لبعض الرسائل.

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