เมื่อใดควรใช้ -retainCount?


110

ฉันต้องการทราบว่าคุณใช้สถานการณ์ใด-retainCountจนถึงขณะนี้และในที่สุดปัญหาที่อาจเกิดขึ้นเมื่อใช้งาน

ขอบคุณ.


5
คุณไม่ควรใช้ไฟล์-retainCount.
holex

3
(ยกเว้นเวลาที่คุณควรทำบางครั้งมีประโยชน์มากในการช่วยทำความเข้าใจว่าเกิดอะไรขึ้นตราบใดที่คุณรู้สึกขอบคุณว่าบางครั้งอาจทำให้เข้าใจผิดได้อย่างจริงจังและแน่นอนว่าไม่อนุญาตเลยหากใช้ ARC)
Hot Licks

คำตอบ:


243

คุณไม่ควรใช้-retainCountเพราะมันไม่เคยบอกอะไรที่เป็นประโยชน์ การดำเนินการตามกรอบ Foundation และ AppKit / UIKit นั้นทึบแสง คุณไม่รู้ว่ามีอะไรถูกเก็บไว้ทำไมจึงถูกเก็บรักษาใครเป็นผู้เก็บรักษาเมื่อถูกเก็บรักษาและอื่น ๆ

ตัวอย่างเช่น:

  • คุณคิดว่า[NSNumber numberWithInt:1]จะมีretainCount1 มันไม่มี มันคือ 2
  • คุณคิดว่า@"Foo"จะมีretainCount1 มันไม่มี เป็น 1152921504606846975
  • คุณคิดว่า[NSString stringWithString:@"Foo"]จะมีretainCount1 มันไม่มี อีกครั้งคือ 1152921504606846975

โดยพื้นฐานแล้วเนื่องจากสิ่งใด ๆ สามารถรักษาวัตถุไว้ได้ (ดังนั้นจึงเปลี่ยนแปลงได้retainCount) และเนื่องจากคุณไม่มีแหล่งที่มาของโค้ดส่วนใหญ่ที่เรียกใช้แอปพลิเคชันวัตถุretainCountจึงไม่มีความหมาย

หากคุณกำลังพยายามค้นหาสาเหตุที่วัตถุไม่ได้รับการจัดสรรให้ใช้เครื่องมือ Leaks ในเครื่องมือ หากคุณกำลังพยายามติดตามว่าเหตุใดวัตถุจึงถูกยกเลิกการจัดสรรเร็วเกินไปให้ใช้เครื่องมือ Zombies ในเครื่องมือ

แต่อย่าใช้-retainCount. เป็นวิธีการที่ไร้ค่าอย่างแท้จริง

แก้ไข

ขอให้ทุกคนไปที่http://bugreport.apple.comและขอ-retainCountให้เลิกใช้งาน ยิ่งมีคนขอมากเท่าไรก็ยิ่งดี

แก้ไข # 2

ในการอัปเดต[NSNumber numberWithInt:1]ตอนนี้มีretainCount9223372036854775807 หากรหัสของคุณคาดว่าจะเป็น 2 แสดงว่ารหัสของคุณเสียแล้ว


4
ขอบคุณ @ Dave-Delong สำหรับตัวอย่างของคุณ
Moszi

1
retainCount ขณะนี้จะเป็นประโยชน์สำหรับ singletons. (ตอนนี้คำถามคือวิธีที่มีประโยชน์เป็น singletons ... - (NSUInteger)retainCount{return NSUIntegerMax;})
โจ

8
@ Joe retainCountที่คุณสามารถทำเดี่ยวโดยไม่ต้องเอาชนะ
Dave DeLong

5
@ โจฉันรู้ว่า; Google "objective-c singleton" สำหรับการสนทนาทั้งหมดว่าเหตุใดตัวอย่างนั้นจึงไม่ดีนัก
Dave DeLong

2
สิ่งหนึ่งที่ฉันใช้ - @ DaveDeLong คุณอาจพบว่าสิ่งนี้ผิดเช่นกัน แต่ฉันไม่คิดอย่างนั้น - คือการเขียนทับ deallocs และ inits และใส่ NSLogs ไว้ในนั้น (แม้จะมี ARC) สิ่งนี้ทำให้ฉันมีความคิดที่ดีว่าวัตถุกำลังถูกจัดสรรหรือไม่ซึ่งเป็นคำถามจริงที่เรามักจะพยายามตอบ ..
Dan Rosenstark

50

ไม่เคย!

อย่างจริงจัง. เพียงแค่ไม่ทำมัน

เพียงทำตามแนวทางการจัดการหน่วยความจำและมีเพียงปล่อยสิ่งที่คุณalloc, newหรือcopy(หรือสิ่งที่คุณเรียกว่าretainเมื่อเดิม)

@bbum กล่าวว่าที่ดีที่สุดที่นี่ใน SOและในรายละเอียดมากขึ้นในบล็อกของเขา


8
เพราะคุณจะคิดว่าคุณกำลังนับหน่วยความจำ แต่คุณจะทำผิด
Abizern

@Abizern - แล้วสถานการณ์ซิงเกิลตันในคำตอบอื่น ๆ ล่ะ?
Moszi

3
ในการเพิ่มสิ่งนี้ข้อมูลใด ๆ ที่คุณจะได้รับ-retainCountสามารถรับได้ (พร้อมรายละเอียดเพิ่มเติม) จากเครื่องมือและเครื่องมือต่างๆ
Dave DeLong

3
เพื่อเพิ่มสิ่งที่เดฟพูด; จำนวนคงที่แน่นอนของวัตถุคือรายละเอียดการนำไปใช้งาน ทั้งรายละเอียดภายในของวัตถุและ / หรือรายละเอียดของวัตถุอื่นใดที่วัตถุอาจถูกส่งผ่าน โทรretain, retain, retain, autorelease, autorelease, autoreleaseอาจเป็นผลที่ถูกต้องสมบูรณ์ของการส่งผ่านวัตถุผ่าน UIKit API เช่น
bbum

2
@ d11wtq ถ้า RetainCount เคย == 0 ความเป็นเอกฐานสำเร็จแล้ว!
bbum

14

Autoreleased object เป็นกรณีหนึ่งที่การตรวจสอบ -retainCount ไม่เป็นข้อมูลและอาจทำให้เข้าใจผิดได้ จำนวนการเก็บรักษาจะไม่บอกคุณว่ามีการเรียกใช้อ็อบเจ็กต์กี่ครั้งแล้วดังนั้นจำนวนครั้งที่ปล่อยออกมาเมื่อพูลการปล่อยอัตโนมัติในปัจจุบันหมดลง


1
ขอบคุณ - นี่เป็นจุดที่ดี นี่เป็นคำตอบแรกซึ่งมีเหตุผลที่อธิบายได้ว่าทำไมไม่ใช้ RetainCount นอกเหนือจาก "don't" ทั่วไป
Moszi

1
@ มอสซี: คำถามของคุณคือ "เมื่อใดควรใช้ RetainCount?" - ถ้าคุณไม่ได้ตั้งใจถามคำถามนั้นคุณควรถามอย่างอื่น
Chuck

@chuck - จริงๆแล้วฉันสนใจ "ควรใช้เมื่อไหร่" แต่ดูเหมือนว่าทุกคำตอบจะเป็น "ไม่เคย" ... แต่ - ฉันเดาว่าคุณพูดถูก ฉันจะปล่อยให้คำถามเปิดไว้สองสามวันและหากไม่มีคำตอบอื่นใดอีกแล้วฉันก็จะยอมรับว่า "ไม่เคย" เป็นคำตอบ
Moszi

10

ฉันไม่พบ retainCounts ประโยชน์มากเมื่อตรวจสอบโดยใช้ 'เครื่องมือ'

ใช้เครื่องมือ 'การจัดสรร' ตรวจสอบให้แน่ใจว่า 'บันทึกจำนวนอ้างอิง' เปิดอยู่และคุณสามารถเข้าไปในออบเจ็กต์ใดก็ได้และดูประวัติการเก็บรักษา

ด้วยการจับคู่การจัดสรรและการเผยแพร่คุณจะได้ภาพที่ดีเกี่ยวกับสิ่งที่เกิดขึ้นและมักจะแก้ไขกรณีที่ยากลำบากเหล่านั้นซึ่งมีบางอย่างไม่ได้รับการปลดปล่อย

สิ่งนี้ไม่เคยทำให้ฉันผิดหวัง - รวมถึงการค้นหาข้อบกพร่องใน iOS รุ่นเบต้ารุ่นแรก ๆ


5

ดูเอกสารของ Apple เกี่ยวกับ NSObject มันค่อนข้างครอบคลุมคำถามของคุณ: NSObject RetainCount

ในระยะสั้น RetainCount อาจไม่มีประโยชน์สำหรับคุณเว้นแต่คุณจะติดตั้งระบบการนับอ้างอิงของคุณเอง (และฉันเกือบจะรับประกันได้ว่าคุณจะไม่มี)

ในคำพูดของ Apple RetainCount คือ "โดยทั่วไปแล้วจะไม่มีค่าในการแก้ปัญหาการจัดการหน่วยความจำ"


ก่อนอื่นขอขอบคุณสำหรับคำตอบ โดยปกติแล้วปฏิกิริยาตอบสนองของผู้คนต่อคำถามนี้คือ "ไม่เคย" (ดูคำตอบ) จริงๆแล้ว "ไม่มีค่าในการดีบัก" ไม่ได้หมายความว่า "ไม่เคย" ดังนั้นคำถามของฉันคือ - ทำไมความรู้สึกที่แข็งแกร่งที่ไม่ได้ใช้มัน (เช่นในการใช้งานซิงเกิลตัน - หนึ่งในคำตอบอีกครั้ง)
Moszi

ฉันเดาว่าคุณจะต้องให้ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณใช้ การใช้งานที่ยอมรับได้จะเป็นไปตามคำแนะนำของ Apple ซึ่งจะแทนที่ RetainCount เพื่อใช้ระบบการนับอ้างอิงของคุณเอง แต่ในทางปฏิบัติคุณจะไม่เห็นสิ่งนั้น (ฉันไม่เคยมีเลย) ปฏิกิริยาที่รุนแรงโดยทั่วไปมาจากข้อเท็จจริงที่ Apple เองได้ให้การสนับสนุน (ในกลุ่มอีเมลเอกสารฟอรัม dev ฯลฯ ) เพื่อปล่อยให้ RetainCount อยู่คนเดียว
lxt

1
@Moszi: การดีบักเป็นสถานการณ์เดียวที่คนส่วนใหญ่สามารถคิดได้ว่ามันมีค่าดังนั้นหากมันไม่น่าเชื่อถือที่นั่นก็ไม่มีประโยชน์ คุณนึกถึงการใช้งานอะไรอีกบ้าง?
Chuck

4

แน่นอนว่าคุณไม่ควรใช้วิธีการ RetainCount ในโค้ดของคุณเนื่องจากความหมายของค่าของมันขึ้นอยู่กับจำนวน autoreleases ที่ถูกนำไปใช้กับวัตถุและนั่นคือสิ่งที่คุณไม่สามารถคาดเดาได้ อย่างไรก็ตามมันมีประโยชน์มากสำหรับการดีบัก - โดยเฉพาะอย่างยิ่งเมื่อคุณค้นหาการรั่วไหลของหน่วยความจำในโค้ดที่เรียกใช้เมธอดของวัตถุ Appkit นอกลูปเหตุการณ์หลักและไม่ควรเลิกใช้งาน

ในความพยายามของคุณที่จะทำให้ประเด็นของคุณคุณได้กล่าวเกินจริงถึงลักษณะของคุณค่าที่ไม่อาจหยั่งรู้ได้ เป็นความจริงที่ไม่ใช่การนับอ้างอิงเสมอไป มีค่าพิเศษบางอย่างที่ใช้สำหรับแฟล็กตัวอย่างเช่นเพื่อระบุว่าไม่ควรยกเลิกการจัดสรรอ็อบเจ็กต์ ตัวเลขเช่น 1152921504606846975 ดูลึกลับมากจนกว่าคุณจะเขียนเป็นเลขฐานสิบหกและได้ 0xffffffffffffffff และ 9223372036854775807 เป็น 0x7fffffffffffffff ในเลขฐานสิบหก และไม่น่าแปลกใจเลยที่ใครบางคนจะเลือกใช้ค่าเช่นนี้เป็นแฟล็กเนื่องจากต้องใช้เวลาเกือบ 3000 ปีในการได้รับ RetainCount ให้สูงเท่ากับจำนวนที่มากขึ้นโดยสมมติว่าคุณเพิ่มค่า RetainCount 100,000,000 ครั้งต่อวินาที


3

คุณจะได้รับปัญหาอะไรบ้างจากการใช้งาน? สิ่งที่ได้ก็คือส่งคืนจำนวนการเก็บรักษาของวัตถุ ฉันไม่เคยโทรหามันและคิดไม่ออกว่าจะมีเหตุผลอะไร ฉันได้แทนที่มันใน singletons เพื่อให้แน่ใจว่าพวกเขาไม่ได้ถูกจัดสรร


2
ไม่มีเหตุผลที่จะแทนที่ในกรณีซิงเกิลตัน ไม่มีเส้นทางรหัสใน Foundation / CoreFoundation ที่ใช้retainCountสำหรับการจัดการหน่วยความจำ
bbum

ไม่ปล่อยใช้เพื่อตัดสินใจว่าควรเรียก dealloc หรือไม่?
ughoavgfhw

2
ไม่; การใช้งานภายในของการรักษา / รีลีส / การปล่อยอัตโนมัติมีรากฐานที่ลึกซึ้งใน CoreFoundation และไม่ใช่สิ่งที่คุณคาดหวัง ไปคว้าแหล่ง CoreFoundation (มีให้) แล้วดู
bbum

3

คุณไม่ควรกังวลเกี่ยวกับการรั่วไหลของหน่วยความจำจนกว่าแอปของคุณจะเริ่มทำงานและทำสิ่งที่เป็นประโยชน์

เมื่อเป็นเช่นนั้นให้เปิดเครื่องมือและใช้แอพและดูว่าหน่วยความจำรั่วเกิดขึ้นจริงหรือไม่ ในกรณีส่วนใหญ่คุณสร้างออบเจ็กต์ด้วยตัวเอง (คุณจึงเป็นเจ้าของ) และลืมปล่อยมันหลังจากที่ทำเสร็จแล้ว

อย่าพยายามเพิ่มประสิทธิภาพโค้ดของคุณในขณะที่คุณกำลังเขียนมันการคาดเดาของคุณเกี่ยวกับสิ่งที่อาจทำให้หน่วยความจำรั่วหรือใช้เวลานานเกินไปมักจะผิดเมื่อคุณใช้งานแอปตามปกติ

พยายามเขียนโค้ดที่ถูกต้องเช่นถ้าคุณสร้างออบเจ็กต์โดยใช้การจัดสรรและสิ่งนั้นให้แน่ใจว่าคุณปล่อยมันอย่างถูกต้อง


0

คุณไม่ควรใช้ในโค้ดของคุณ แต่สามารถช่วยได้อย่างแน่นอนเมื่อทำการดีบั๊ก


0

อย่าใช้ -retainCount ในรหัสของคุณ อย่างไรก็ตามหากคุณใช้คุณจะไม่เห็นว่ามันส่งกลับศูนย์ ลองคิดดูว่าทำไม :-)


0

ตัวอย่างที่ใช้ในโพสต์ของ Dave คือ NSNumber และ NSStrings ... ดังนั้นหากคุณใช้คลาสอื่น ๆ เช่น UIViews ฉันมั่นใจว่าคุณจะได้รับคำตอบที่ถูกต้อง (จำนวนที่คงไว้ขึ้นอยู่กับการนำไปใช้และสามารถคาดเดาได้)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.