การจัดการหน่วยความจำใน Objective-C และการตั้งค่าตัวชี้เป็นศูนย์

ตัวชี้ไปยังวัตถุจะไปที่ nil เมื่อนับเป็น 0 หรือเมื่อมีการเรียกการจัดสรรคืน ทำไมหรือทำไมไม่?


person SVA    schedule 09.01.2010    source แหล่งที่มา


คำตอบ (4)


ไม่ จะไม่ทำเช่นนั้น เนื่องจากการจัดสรรคืนไม่มีอำนาจในการเปลี่ยนตัวชี้ ทำได้เพียงคุณส่ง ตัวชี้ ไปยังตัวชี้เท่านั้น

หากคุณต้องการให้แน่ใจว่าตั้งค่าเป็นศูนย์ คุณต้องดำเนินการด้วยตัวเอง

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

จริงๆ แล้วฉันโน้มตัวไปทางค่ายหลัง แต่ฉันเข้าใจได้ว่าทำไมผู้คนถึงต้องการปกป้องตัวเองจากการเข้าถึงหน่วยความจำที่ว่าง (การเขียนโปรแกรมเชิงป้องกันนั้นไม่ค่อยเป็นความคิดที่ไม่ดี)

person paxdiablo    schedule 09.01.2010
comment
ฉันตั้งค่ามาโครให้ปล่อยตัวชี้อย่างปลอดภัยและตั้งค่าเป็น nil - person notnoop; 09.01.2010
comment
+1 FYI เมื่อใช้การรวบรวมขยะ __weak พอยน์เตอร์จะเป็นศูนย์ในตัวเอง นอกจากนี้ การใช้มาโครในการทำเช่นนี้อาจทำให้เกิดข้อผิดพลาดได้ ดังที่ฉันกล่าวถึงในคำตอบด้านล่าง - person Quinn Taylor; 09.01.2010
comment
หากคุณไม่ได้ตั้งค่าการอ้างอิงเป็น n เมื่อคุณเผยแพร่ Leaks จะไม่สามารถบอกคุณได้ว่ามีหน่วยความจำรั่ว ท้ายที่สุดแล้ว เท่าที่ Leaks กังวล คุณมีข้อมูลอ้างอิงที่ถูกต้อง แม้ว่าคุณจะคิดว่าข้อมูลอ้างอิงนั้น ใช้ไม่ได้อีกต่อไป (การรักษาลูกค้ามากเกินไป) - person Kendall Helmstetter Gelner; 10.01.2010
comment
จุดดี. กรณีที่คุณยังคงรักษาตัวชี้ที่ถูกต้องซึ่งคุณไม่ได้ใช้อีกต่อไปจะถือว่าเป็นหน่วยความจำที่ถูกทิ้งร้าง แทนที่จะเป็นการรั่วไหล น่ายินดีที่คุณมีแนวโน้มที่จะเห็นเครื่องมือสำหรับตรวจจับหน่วยความจำที่ถูกละทิ้งในเครื่องมือเวอร์ชันอนาคต... :-) - person Quinn Taylor; 15.04.2010

ภายใต้โมเดลหน่วยความจำแบบรีเทนต์แบบปกติ ไม่มี เมื่อเปิดใช้งานการรวบรวมขยะ สิ่งนี้จะเกิดขึ้นหากมีการประกาศตัวชี้เป็น __weak (สำหรับออบเจ็กต์ Objective-C ค่าเริ่มต้นคือ __strong) ตัวรวบรวมขยะจะลบการอ้างอิงที่อ่อนแอสำหรับคุณเมื่อถูกกำจัด ซึ่งทำให้เหมาะสำหรับการชี้ไปยังผู้รับมอบสิทธิ์และวัตถุกึ่งชั่วคราว ดูเพิ่มเติมที่ NSPointerArray, NSMapTable และ NSHashTable และการสนับสนุนความสัมพันธ์ที่อ่อนแอเช่นกัน (หมายเหตุ: เราต้องเข้าใจว่าการอ้างอิงที่คาดเดายากจะไม่ป้องกันไม่ให้วัตถุถูกรวบรวมขยะ แต่จะมีค่าเป็นศูนย์เมื่อไม่มีการอ้างอิงที่คาดเดายากชี้ไปยังที่อยู่เดียวกัน ดู เอกสารนี้ เพื่อสรุปโดยย่อเกี่ยวกับพฤติกรรมนี้)

การรวบรวมขยะ Objective-C ยังมีประโยชน์อื่นๆ อีกมากมาย และฉันขอแนะนำให้ใช้อย่างเต็มที่หากทำได้ (ใช้งานได้บน OS X 10.5+ แต่ไม่ใช่บน iPhone OS) การปรับปรุงประสิทธิภาพใน Snow Leopard นั้นน่าประทับใจที่สุด และมันก็ชั่วร้ายอย่างรวดเร็วตั้งแต่เริ่มต้น

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

อย่างไรก็ตาม โดยทั่วไปฉัน ไม่ ไม่มีค่าใน -dealloc เนื่องจากหน่วยความจำที่คุณกำลังแก้ไขกำลังจะถูกเรียกคืน และหากส่วนอื่น ๆ ของโค้ดอาจพบข้อผิดพลาดเนื่องจากการใช้ค่าที่เผยแพร่ พวกเขาไม่ควรใช้วัตถุที่จัดสรรคืนตั้งแต่แรก (สิ่งนี้มักเกิดขึ้นเมื่อวัตถุหนึ่งไม่ได้เก็บรักษาอีกวัตถุไว้อย่างถูกต้อง และวัตถุหลังถูกจัดสรรคืน เหลือ ตัวชี้ห้อย.) ข้อยกเว้นที่เป็นไปได้อาจรวมถึงการแยกส่วนแบบเป็นขั้น ซึ่งการอ้างอิงที่ไม่ใช่ศูนย์อาจทำให้เกิดปัญหาภายในการจัดสรรคืนเอง แต่ลักษณะการทำงานประเภทนี้โดยทั่วไปจะไม่ (และไม่ควร) เกิดขึ้นเมื่อทำลายวัตถุ

person Quinn Taylor    schedule 09.01.2010

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

person D.C.    schedule 09.01.2010
comment
+1 นี่เป็นคำแนะนำที่ดี โดยเฉพาะอย่างยิ่งสำหรับอินสแตนซ์และตัวแปรคงที่ และเพิ่มขึ้นเป็นสองเท่าภายใต้การรวบรวมขยะ ซึ่งคุณสามารถสะสมการอ้างอิงที่แข็งแกร่งไปยังหน่วยความจำที่ไม่จำเป็นโดยไม่ตั้งใจซึ่งจะไม่ถูกเรียกคืนตามที่ต้องการ ฉันคิดว่าบางคนแค่ต้องการวิธีแก้ปัญหา Magic Bullet เพื่อจะได้ไม่ต้องคิดถึงปัญหานี้ - person Quinn Taylor; 09.01.2010

ลองนึกถึงสถานการณ์นี้:

void *p = malloc (100);

while (someCondition)
{
    //  do something with p
}

free (p);

// p is not set to NULL for you, it still points to where it always did

ในทำนองเดียวกัน เมื่อมีการจัดสรรวัตถุ Objective-C ตัวชี้ไปยังวัตถุนั้นยังคงชี้ไปยังตำแหน่งที่วัตถุนั้นอยู่ สิ่งนี้ทำให้เกิดข้อผิดพลาดเมื่อมีการจัดสรรวัตถุอื่นลงในพื้นที่เดียวกัน (หรือแม้ว่าจะไม่มีการจัดสรรสิ่งใดลงในพื้นที่เดียวกันก็ตาม)

person dreamlax    schedule 09.01.2010