Một người bạn của tôi đã khám phá ra một số hành vi kỳ lạ với NSDictionary, và tôi tò mò là tại sao nó lại xảy ra. Hãy xem xét mã sau:Tại sao cuộc gọi mục tiêu C này xuất hiện để treo?
NSDictionary *dict = [[NSDictionary alloc] init];
// Oops, we can't mutate an NSDictionary
[dict setObject:[[NSNull alloc] init] forKey:@"test"];
NSLog(@"Set");
Mã tạo ra cảnh báo khi biên dịch "'NSDictionary' không thể trả lời 'setObject: forKey:'". Đó là tất cả tốt và tốt, và nếu bạn chạy nó dù sao, bạn sẽ nhận được kết quả này trong bảng điều khiển
- [__ NSCFDictionary setObject: forKey:]: biến đổi phương pháp gửi đến đối tượng bất biến
Một lần nữa, chính xác những gì bạn mong đợi sẽ xảy ra. Tuy nhiên, tại thời điểm này, ứng dụng không bị lỗi hoặc chấm dứt do ngoại lệ không bị bắt buộc. Phương thức setObject: forKey: đơn giản không bao giờ trả về và ứng dụng xuất hiện để treo; NSLog
sau không bao giờ được thực thi. Nếu bạn cố gắng bước qua hoặc vào phương thức sử dụng GDB, việc gỡ lỗi dường như kết thúc, nhưng không có bất kỳ thông báo lỗi rõ ràng nào. Ứng dụng tiếp tục chạy, nhưng trình gỡ lỗi không cung cấp đầu mối về vị trí trong mã thực thi là "bị kẹt".
Điều gì đang xảy ra ở đây? Ứng dụng thực sự đang làm gì trong trường hợp này và tại sao nó không bị lỗi với một NSInternalInconsistencyException hoặc một cái gì đó tương tự?
Chỉnh sửa: Đối với những người đã hỏi, tôi đang chạy XCode 4.1 trên OS X Lion (10.7.2), xây dựng bằng "Trình biên dịch LLVM của Apple 2.1". Tôi đang sử dụng tất cả các thiết lập mặc định bạn nhận được với một dự án Cocoa mới trong XCode 4. Tôi trải nghiệm cùng một hành vi không bị treo bất kể tôi có gỡ lỗi chương trình hay chỉ "Chạy" nó. Thay đổi từ tòa nhà Gỡ lỗi sang tòa nhà Phát hành không có sự khác biệt. Tôi thậm chí có thể xác định vị trí các tập tin .app bằng tay trong Finder và nhấp đúp chuột vào nó để thực hiện nó bên ngoài của XCode, và nó vẫn không sụp đổ.
Hãy thử chạy ứng dụng không nằm trong trình gỡ lỗi; Tôi đặt cược nó treo cứng. Tôi tìm thấy môi trường trình gỡ lỗi có thể có một số hiệu ứng không mong muốn trên môi trường thời gian chạy đặc biệt là xung quanh ngoại lệ và những gì sẽ xảy ra khi bạn nhấn chúng. –
Khi ngoại lệ được ném, kiểm soát sẽ tiếp tục với bất cứ điều gì bắt ngoại lệ, * không * dòng tiếp theo sau khi ngoại lệ. Trong ví dụ của bạn hoặc là trình gỡ lỗi, hoặc ruột của thời gian chạy, "bắt" ngoại lệ. Trong mọi trường hợp, bạn sẽ không mong đợi NSLog xảy ra sau khi -setObject: forKey: đã ném một ngoại lệ. –
@VincentGable: Đồng ý, nếu chương trình bị hỏng, tôi sẽ không ngạc nhiên chút nào khi NSLog không được gọi. Điều làm tôi ngạc nhiên là nó không bị treo hoặc tiến tới dòng tiếp theo. Nó có vẻ như nó nên làm một hay khác. Đối với những người đã hỏi, tôi đã cập nhật câu hỏi với một số chi tiết bổ sung về môi trường mà tôi đang sử dụng. –