ViewController responseToSelector: ข้อความที่ส่งไปยังอินสแตนซ์ที่ถูกจัดสรร (CRASH)


95

ตกลงนี่คือข้อตกลงฉันเกลียดการตั้งคำถามเกี่ยวกับการแก้ไขข้อบกพร่องและข้อขัดข้องของฉัน เพราะปกติฉันจะจัดการพวกเขาด้วยตัวเอง แต่ฉันก็ไม่สามารถหลีกเลี่ยงปัญหานี้ได้แม้ว่าจะดูคำถามหลายข้อแล้วก็ตาม

ตกลงนี่คือปัญหาฉันพบว่าแอปของฉันสุ่มเปิดและปิดการหยุดทำงานด้วยการติดตามสแต็กนี้:

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

ViewControllerอาจแตกต่างกันไปที่ไหนบางครั้งสถานที่ที่รหัสของฉันขัดข้องไม่มีความเกี่ยวข้องกับรายการนั้นViewControllerและไม่ได้เป็นเจ้าของหรือเรียกมันว่า

นอกจากนี้เพื่อรับการติดตามคอนโซลนั้นฉันได้เปิดใช้งาน Zombies มิฉะนั้นฉันจะไม่ได้รับการพิมพ์คอนโซลเลยฉันจะได้รับ: objc_msgSendซึ่งฉันรู้ว่าฉันกำลังส่งข้อความบางอย่างที่เผยแพร่ แต่ฉันไม่พบว่ามันอยู่ที่ไหน ... ฉันติดอยู่จริงๆ! โดยปกติฉันมักจะแก้ไขข้อขัดข้องของฉันดังนั้นฉันจึงติดอยู่กับเรื่องนี้จริงๆ

อีกครั้งสิ่งนี้ขัดข้องในสถานที่ต่างๆในเวลาที่ต่างกันทั้งในและนอก และสถานที่ที่เกิดปัญหาแทบไม่มีความเกี่ยวข้องกับไฟล์ViewController. และฉันพบว่าสิ่งนี้สับสนมาก

คุณต้องการรหัสของฉันหรือไม่? ฉันมีไฟล์จำนวนมากและเนื่องจากมันขัดข้องในที่ต่างๆการแจกจ่ายโค้ดของฉันจะเป็นเรื่องยุ่ง!

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

ขอบคุณทุกคน ...


คุณดูคำถามนี้ไหมstackoverflow.com/questions/1585688/…
self

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

วิธีการเปิดใช้งานเบรกพอยต์เชิงสัญลักษณ์ ลองเพิ่มสิ่งเหล่านี้: wiki.zemingo.com/index.php?title=Symbolic_Breakpoints
Stavash

@RobertRyan ฉันใช้ presentModalViewController ฉันไม่ได้เพิ่มเป็น subview
MCKapur

ในกรณีของฉันตัวควบคุมมุมมองลูกของฉันมี webView และ VC ลูกเป็นผู้รับมอบสิทธิ์สำหรับ scrollView ของ webView ฉันต้องการลบการอ้างอิงผู้รับมอบสิทธิ์ด้วยตนเองในระหว่าง dealloc / viewWillDisappear ไม่เช่นนั้นฉันเกิดข้อขัดข้อง หวังว่ามันจะช่วยใครบางคน
Dermot

คำตอบ:


169

ใช้เครื่องมือเพื่อติดตามข้อผิดพลาดของอินสแตนซ์ที่ไม่ได้จัดสรร กำหนดโปรไฟล์แอปพลิเคชันของคุณ ( Cmd ⌘+ I) และเลือกเทมเพลตZombies หลังจากที่แอปพลิเคชันของคุณทำงานแล้วให้ลองหยุดทำงาน คุณควรจะได้รับสิ่งนั้น:

ป้อนคำอธิบายภาพที่นี่

คลิกที่ลูกศรถัดจากที่อยู่ในป๊อปโอเวอร์เพื่อแสดงออบเจ็กต์ที่ถูกเรียกหลังจากเลิกจัดสรร

ป้อนคำอธิบายภาพที่นี่

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

คอลัมน์RefCtแสดง RetainCount หลังจากเรียกใช้การดำเนินการและResponsible Callerจะแสดงชื่อคลาสและวิธีการที่ดำเนินการ เมื่อคุณดับเบิลคลิกที่การเก็บรักษา / รีลีสใด ๆ เครื่องมือจะแสดงบรรทัดของโค้ดที่ดำเนินการนี้ (หากไม่ได้ผลคุณสามารถตรวจสอบการโทรโดยเลือกและเลือกคู่ของมันในบานหน้าต่างรายละเอียดเพิ่มเติม ):

ป้อนคำอธิบายภาพที่นี่

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


3
ปัญหาอาจไม่ใช่ปัญหาล่าสุดreleaseโดยเฉพาะ ปัญหาคือใด ๆreleaseที่ไม่สมดุล ฉันยังสามารถล้มเหลวในretainบางสิ่งบางอย่างที่คุณคอยเป็นตัวชี้และอ้างอิงในภายหลัง
Ken Thomases

1
นอกจากนี้ฉันไม่มีเทมเพลตเครื่องมือ Zombie นั่นอาจเป็นเพราะฉันใช้ Xcode Beta 4.5 ฉันจะเปลี่ยนเป็น 4.4 ในระหว่างนี้
MCKapur

2
โอ้ซอมบี้มีให้ในโปรแกรมจำลอง iOS เท่านั้น ฉันไม่สามารถทำงานในโปรแกรมจำลอง iOS ได้กรอบงานและไลบรารีบางส่วนของฉันที่ใช้ไม่รองรับสถาปัตยกรรม
MCKapur

เพียงบันทึกเล็ก ๆ นี่มาจากสิ่งใหม่ใน xcode 5 "เทมเพลตเครื่องมือ Zombies ได้รับการปรับปรุงใน Xcode 5 และตอนนี้รองรับการใช้งานบนอุปกรณ์แล้วการใช้ Zombies บนอุปกรณ์ต้องใช้ iOS 7" บันทึกนี้นำคุณมาโดยฉันและเวลาอันมีค่าของฉัน 2 ชั่วโมง ...
nickfox

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

59

มีปัญหาที่คล้ายกัน ในกรณีของฉัน viewController จำเป็นต้องได้รับเหตุการณ์ navigationController ดังนั้นจึงลงทะเบียนเป็นผู้แทนตัวควบคุมการนำทาง:

 self.navigationController.delegate = self;

ข้อขัดข้องเกิดขึ้นเมื่อตัวควบคุมนั้นถูกยกเลิกการจัดสรร แต่ยังคงเป็นผู้รับมอบสิทธิ์สำหรับตัวควบคุมมุมมอง การเพิ่มรหัสนี้ใน dealloc ไม่มีผล:

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

เนื่องจากเมื่อถึงจุดที่เรียกว่า dealloc ตัวควบคุมมุมมองได้ถูกลบออกจากลำดับชั้นของมุมมองแล้วดังนั้น self.navigationController จึงเป็นศูนย์ดังนั้นการเปรียบเทียบจึงรับประกันว่าจะล้มเหลว! :-(

วิธีแก้ปัญหาคือการเพิ่มรหัสนี้เพื่อตรวจจับ VC ที่ออกจากลำดับชั้นของมุมมองก่อนที่จะทำเช่นนั้นจริง ใช้วิธีการที่นำมาใช้ใน iOS 5 เพื่อตรวจสอบว่าเมื่อใดที่มุมมองจะปรากฏขึ้นและไม่ได้รับการผลักดัน

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

ไม่ล่มอีกต่อไป!


ขอบคุณเช่นกัน - ต้องใช้เวลาค้นหาเพียง 4 ชั่วโมงเพื่อค้นหาโพสต์นี้
daidai

ขอบคุณสำหรับการโพสต์มีปัญหาเดียวกัน ^^
Tyron

ผู้คนหาวิธีแก้ปัญหาที่น่ารำคาญเช่นนี้ได้อย่างไร? ถอดหมวกออก !!
ViruMax

4

สำหรับใครที่แก้ไม่ได้นี่คือเทคนิคอื่น ๆ :

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

คุณสามารถเรียกใช้ Instruments ใน Xcode 5 ได้โดยคลิกที่ป๊อปอัปโครงการ -> แก้ไข Scheme ... โปรไฟล์ -> เครื่องมือและเลือกการจัดสรรหรือการรั่วไหลจากนั้นกำหนดโปรไฟล์แอปของคุณจากนั้นหยุดเครื่องมือคลิกปุ่มข้อมูลในการจัดสรรและ "เปิดใช้งานการตรวจจับ NSZombie" .

อย่างไรก็ตามสำหรับข้อความที่มาจาก com.apple.main-thread โดยตรงสิ่งนี้อาจไม่เปิดเผยอะไรเลย

ฉันกระแทกหัวของฉันเป็นเวลานานกว่าสองชั่วโมงและคำตอบก็กลายเป็นการเปิดตัวมากเกินไปซึ่งฉันค้นพบโดยการแสดงความคิดเห็นสำเนาโครงการของฉันโดยใช้กำลังดุร้ายจนกว่าฉันจะพบผู้กระทำผิด:

[viewController release];
viewController = NULL;

ปัญหาคือ release ไม่ได้ตั้งค่าตัวแปรเป็น NULL

นั่นหมายความว่าการตั้งค่าเป็น NULL การเรียกใช้อีกครั้งการลดจำนวนการอ้างอิงและการปลดปล่อยหน่วยความจำทันทีจนกระทั่งในภายหลังเมื่อตัวแปรที่อ้างอิง viewController เสร็จสิ้น

ดังนั้นให้เปิดใช้ ARC หรือตรวจสอบให้แน่ใจว่าโครงการของคุณใช้ release หรือ NULL อย่างสม่ำเสมอ แต่ไม่ใช่ทั้งสองอย่าง ความชอบของฉันคือใช้ NULL เพราะไม่มีโอกาสที่จะอ้างถึงซอมบี้ แต่มันทำให้การค้นหาตำแหน่งที่ปล่อยวัตถุนั้นยากขึ้น


4

ฉันพบปัญหาเดียวกันใน iOS เมื่อวานนี้ ฉันได้สร้าง IAP ในมุมมองย่อย "เกี่ยวกับ" ของแอปแล้วและฉันได้เพิ่ม Transaction Observer ใน viewDidLoad "เกี่ยวกับ" เมื่อฉันซื้อเป็นครั้งแรกไม่มีปัญหา แต่หลังจากฉันกลับไปที่หน้าต่างหลักและป้อนเกี่ยวกับมุมมองย่อยที่จะซื้ออีกครั้งปัญหา "ข้อความที่ส่งไปยังอินสแตนซ์ที่ถูกจัดสรร" ก็เกิดขึ้นและแอปขัดข้อง

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

หลังจากลบ Transaction Observer ใน dealloc แล้วปัญหาจะได้รับการแก้ไข

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

มันแก้ไขปัญหารันไทม์ของฉัน ... ฉันได้รับzombieวัตถุสำหรับการซื้อ inApp หลังจากขุดไปหลายชั่วโมงฉันก็พบสิ่งนี้ .... ขอบคุณมาก
Mahendra

4

ฉันมีปัญหาที่คล้ายกันมากและฉันพบว่ามันเกิดจากการตั้งค่าตัวแทนของตัวควบคุมการนำทาง

ด้านล่างนี้ช่วยแก้ปัญหาของฉันได้

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}

ขอบคุณ !! เป็นปัญหาเดียวกันที่นี่
pegpeg

2

มีปัญหาเดียวกันใน OS X.

เพื่อแก้วิธีนี้ไม่เพียงพอ- (void)deallocตามที่ @SoftwareEvolved ได้กล่าวไว้แล้ว แต่น่าเสียดายที่- (void)viewWillDisappearสามารถใช้ได้เฉพาะในเวอร์ชัน 10.10 และใหม่กว่า

ฉันแนะนำวิธีการที่กำหนดเองในคลาสย่อย NSViewController ของฉันซึ่งตั้งค่าการอ้างอิงที่เป็นอันตรายต่อซอมบี้ทั้งหมดเป็นศูนย์ ในกรณีของฉันนั่นคือNSTableViewคุณสมบัติ ( delegateและdataSource)

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

นั่นคือทั้งหมด ทุกครั้งที่ฉันกำลังจะลบมุมมองจาก superview ต้องเรียกวิธีนี้


2

ฉันมีปัญหาเดียวกันมันยากที่จะค้นหาว่าผู้ร่วมประชุมทำให้เกิดปัญหาใดเพราะมันไม่ได้ระบุคำสั่งบรรทัดหรือรหัสใด ๆ ดังนั้นฉันจึงลองวิธีใดวิธีหนึ่งบางทีมันอาจจะเป็นประโยชน์สำหรับคุณ

  1. เปิดไฟล์ xib และจากเจ้าของไฟล์เลือก "แสดงตัวตรวจสอบการเชื่อมต่อ" เมนูด้านขวามือ มีการแสดงรายชื่อผู้รับมอบสิทธิ์ตั้งค่าเป็นศูนย์ที่ต้องสงสัย
  2. (เช่นเดียวกับกรณีของฉัน) Property Object เช่น Textfield สามารถสร้างปัญหาได้ดังนั้นตั้งค่าผู้รับมอบสิทธิ์เป็นศูนย์
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

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