Làm thế nào để tìm ra nguyên nhân của lỗi "double free" malloc?


80

Tôi đang lập trình một ứng dụng trong Objective-C và tôi gặp lỗi này:

MyApp (2121,0xb0185000) malloc: *** error for object 0x1068310: double free
*** đặt breakpoint trong malloc_error_break để gỡ lỗi

Nó đang xảy ra khi tôi phát hành NSAutoreleasePool và tôi không thể tìm ra đối tượng nào tôi đang phát hành hai lần.

Làm cách nào để thiết lập điểm dừng của anh ấy?

Có cách nào để biết "đối tượng 0x1068310" này là gì không?


3
bạn có thể muốn gắn thẻ bài đăng này với iPhone cũng như để có được một số người hơn
Benny Wong

4
Đã xóa thẻ "iphone" để chuyển sang các thẻ khác thích hợp hơn.
Quinn Taylor

3
Tôi không thể tưởng tượng tại sao câu hỏi iPhone này lại thiếu thẻ iPhone. Phải có nhiều người theo dõi "iPhone" hơn một số thẻ khác như "autorelease." Nếu bạn muốn tìm "autorelease", bạn tìm kiếm nó, bạn không theo dõi thẻ. Vì vậy, tôi đặt "iPhone" trở lại trong.
Nosredna

6
Lý do tôi loại bỏ thẻ "iphone" là vì không có gì về câu hỏi dành riêng cho iPhone. Liên kết duy nhất là nó xảy ra trong ứng dụng iPhone, nhưng cùng một lỗi có thể xảy ra trong bất kỳ ứng dụng C hoặc Objective-C nào. Tôi không hy vọng rằng những người theo dõi iPhone sẽ tình cờ quan tâm đến điều này - đúng hơn, đó sẽ là những người tìm kiếm những thứ như "miễn phí gấp đôi" hoặc "malloc_error_break" và nếu họ ném "iPhone", nó vẫn sẽ xuất hiện . Đừng tranh cãi về các thẻ, nhưng hãy cân nhắc rằng có lẽ những người trả lời có thể biết câu hỏi thuộc về nơi nào tốt nhất.
Quinn Taylor

3
Câu hỏi này ít nhất là về Ca cao. Nếu thẻ iPhone bị xúc phạm, còn thẻ ca cao thì sao? Mục đích rõ ràng áp dụng cho Objective-C trên Cocoa trong XCode. Không phải Objective-C trên Windows, Linux hoặc bên ngoài ngữ cảnh của XCode.
runako

Câu trả lời:


38

Bạn sẽ tìm ra đối tượng là gì khi bạn phá vỡ trình gỡ lỗi. Chỉ cần tra cứu ngăn xếp cuộc gọi và bạn sẽ tìm thấy nơi bạn giải phóng nó. Điều đó sẽ cho bạn biết đó là đối tượng nào.

Cách dễ nhất để đặt điểm ngắt là:

  1. Đi tới Run -> Show -> Breakpoints ( ALT- Command-B )
  2. Cuộn xuống cuối danh sách và thêm biểu tượng malloc_error_break

1
Tôi đã thử điều đó, nhưng tôi nhận được: không thể phân tán malloc_error_break .... nó có nghĩa là gì?
gonso

3
Không có trợ giúp cho tự động xin vui lòng gấp đôi miễn phí. Anh ấy cần Zombies
Rog

58
@gonso - Chỉ tò mò, nếu điều này không hiệu quả với bạn, tại sao bạn lại chấp nhận nó như một câu trả lời?
Quinn Taylor

8
Trong Xcode 4.3.2, các điểm ngắt có thể được tìm thấy trong Chế độ xem → Bộ điều hướng → Hiển thị Bộ điều hướng điểm ngắt hoặc ⌘6 (Cmd-6)
Andreas Ley

46

Khi một đối tượng được "giải phóng hai lần", nguyên nhân phổ biến nhất là bạn (không cần thiết) giải phóng một đối tượng đã tự động phát hành và sau đó nó sẽ được tự động phát hành khi nhóm autorelease có chứa bị trống.

Tôi thấy rằng cách tốt nhất để theo dõi bản phát hành bổ sung là sử dụng biến môi trường NSZombieEnabled cho tệp thực thi bị ảnh hưởng trong Xcode. Để biết tóm tắt nhanh về cách sử dụng nó, hãy xem trang wiki CocoaDev này . (Ngoài trang này, Apple đã ghi lại một số mẹo cực kỳ ít người biết đến nhưng hữu ích để gỡ lỗi mã trong Xcode, một số trong số đó đã lưu phần mềm của tôi nhiều hơn một vài lần. Tôi khuyên bạn nên xem Lưu ý kỹ thuật này trên developer.apple.com - link chuyển đến phần trong khuôn khổ Cocoa's Foundation).

Chỉnh sửa: Bạn thường có thể theo dõi đối tượng vi phạm trong trình gỡ lỗi Xcode, nhưng thường dễ dàng hơn nhiều nếu bạn sử dụng Công cụ để hỗ trợ bạn. Từ Xcode, chọn Run → Start With Performance Tool → Object Allocations và bạn sẽ có thể theo dõi đối tượng vi phạm trở lại nơi nó được tạo. (Điều này sẽ hoạt động tốt nhất nếu bạn đã kích hoạt zombie như đã thảo luận ở trên.) Lưu ý: Snow Leopard thêm công cụ Zombies vào Instruments, cũng có thể truy cập được từ menu Run. Có thể đáng giá 29 đô la một mình! ;-)

Cũng có một câu hỏi SO liên quan ở đây .


1
Trang wiki CocoaDev được liên kết trong câu trả lời đã chết :(
Devarshi


13

Tôi chỉ muốn thêm kinh nghiệm của mình ngoài câu trả lời của Quinn Taylor.

Trong một trong các ứng dụng của tôi, tôi phải phân tích cú pháp và lưu dữ liệu vào các đối tượng dữ liệu cốt lõi và sau đó đưa các đối tượng này hiển thị trên các khung nhìn. Trên thực tế, ứng dụng hoạt động tốt và không gặp sự cố nào, cho đến khi tôi cố gắng thực hiện một bài kiểm tra căng thẳng về việc điều hướng qua lại nhiều lần, cố gắng mở nhiều chế độ xem càng nhanh càng tốt. Ứng dụng bị lỗi với thông báo trên.

Tôi đã thử tất cả các phương pháp mà Quinn gợi ý trong câu trả lời của anh ấy và vẫn không tìm ra nguyên nhân chính xác là do đâu.

Tôi đặt NSZombieEnabled = YES và NSStackLogging = YES, chạy lệnh shell malloc_history để tìm hiểu lý do, nhưng vẫn không gặp may. Nó luôn chỉ ra nơi tôi lưu dữ liệu vào các đối tượng dữ liệu cốt lõi, trên thực tế, tôi đã kiểm tra hàng nghìn lần các đối tượng được phát hành quá mức ở đó, không có gì kỳ lạ.

Chạy trong Instruments với các công cụ khác nhau (Phân bổ, Rò rỉ, v.v.) vẫn không giúp được gì. Kích hoạt Bảo vệ Malloc vẫn không có gì.

Giải cứu cuối cùng: Tôi đã cố gắng quay lại các khung nhìn nơi các đối tượng được lấy từ Dữ liệu cốt lõi và gửi thông báo giữ lại cho tất cả các đối tượng này, đồng thời lưu ý những thay đổi này. Nó đã giải quyết được vấn đề !!!

Vì vậy, tôi phát hiện ra rằng tôi đã không giữ lại được, đó chính xác là nguyên nhân. Chỉ muốn chia sẻ kinh nghiệm của tôi để bạn có một giải cứu khác cho ứng dụng của mình.


9

Mở bảng điều khiển trình gỡ lỗi bằng cách nhấn Cmd + Shift + R. Đây, gõ

break malloc_error_break

để đặt một điểm ngắt ở đầu malloc_error_break hàm.

Nếu bạn muốn tìm hiểu đối tượng nằm ở địa chỉ 0x1068310, bạn có thể nhập thông tin sau vào bảng điều khiển trình gỡ lỗi:

print-object 0x1068310

Tất nhiên, bạn phải làm điều này trong khi đối tượng vẫn còn sống - nếu đối tượng đã được giải phóng vào thời điểm bạn làm điều này, thì điều này sẽ không hoạt động.


Đây là autorelease, anh ấy cần Zombies.
Rog

1
Cuối cùng những gì tôi đã làm là gọi phương thức "đáng ngờ" bên ngoài AutoreleasePoll. Thật buồn cười khi nghĩ rằng tôi vẫn nhận được cảnh báo, nhưng không có điểm ngắt nào bị ảnh hưởng. Tôi chỉ nhận xét các khối cho đến khi tôi tìm thấy dòng. Tôi đang tự động viết lại một chuỗi được tạo bằng stringWithFormat (không phân bổ hoặc sao chép). Cảm ơn tất cả các mẹo của bạn! Gonso
gonso

Đối với loại lỗi cụ thể này, việc phá vỡ trên malloc_error_break chưa bao giờ giúp tìm ra vấn đề - nó luôn yêu cầu kích hoạt zombie.
Quinn Taylor

Xem tại đây để biết hướng dẫn về cách đặt điểm ngắt cho malloc_error_break trong XCode 4: stackoverflow.com/questions/6969407/…
benvolioT 30/09/11

1
@Zammbi: Hãy thử sử dụng pobí danh hoặc tương đương expr -o. Trong những năm kể từ khi câu trả lời này ban đầu được viết, công cụ gỡ lỗi được sử dụng bởi Xcode đã được thay đổi từ GDB thành LLDB và LLDB có một bộ lệnh khác.
Adam Rosenfield

4

Đối với tôi, vấn đề đã được giải quyết bởi

(gdb) call (void)_CFAutoreleasePoolPrintPools()

ngay sau vụ va chạm. Địa chỉ ở trên cùng của ngăn xếp là địa chỉ của thủ phạm. Ném vào một retainvà thì đấy.

Địa chỉ được cung cấp trong thông báo nhật ký không đưa tôi đến bất cứ đâu. Nó không bao giờ xuất hiện trong bất kỳ Nhạc cụ nào khác nhau. Rõ ràng là một con trỏ đến một số dữ liệu nội bộ đã được giải phóng.


4

Thêm một điểm ngắt biểu tượng trong Xcode 4

Chỉ cần cập nhật để làm cho điều này có liên quan đến Xcode 4 ...

Từ Hướng dẫn sử dụng Xcode 4 :

Để thêm một điểm ngắt biểu tượng. . .

  1. Ở góc dưới cùng bên trái của trình điều hướng điểm ngắt, nhấp vào nút Thêm.
  2. Chọn Thêm điểm ngắt biểu tượng.
  3. Nhập tên biểu tượng vào trường Biểu tượng.
  4. Nhấp vào Xong.


2

Kiểm tra các lớp của bạn và xem theo phương thức dealloc. Hãy chắc chắn rằng bạn quan tâm đến việc gọi điện[super dealloc].

Tôi đã gặp vấn đề chính xác này và phát hiện ra rằng tôi đã gọi [self dealloc]thay thế. Chỉ là không chú ý.


2

Vui lòng xem các bước dưới đây để biết cách tìm đối tượng miễn phí và làm ứng dụng gặp sự cố.

1) Nhấp vào "Bộ điều hướng điểm ngắt ".
2) Sau đó nhấp vào nút " + " bên dưới.
3) Thêm " Điểm ngắt biểu tượng ... " từ danh sách.
4) Thêm từ khóa " malloc_error_break " vào tùy chọn " Symbol ".

Hoặc bạn cũng có thể tham khảo cách trình bày GIF dưới đây.

Gửi lại GIF


1

Điều này thường do một số trình kiểm tra gây ra, chẳng hạn như safari hoặc xem trước safari. Tham khảo bài đăng hoặc bài đăngcâu hỏi .

Bỏ chọn AutoMatically Show Web ...., sẽ loại bỏ vấn đề này.

Lưu ý, chỉ đóng safari hoặc xem trước safari sẽ không loại bỏ được vấn đề này. Và bạn phải bỏ chọn cả hai chế độ xem trước safari và safari.

Nếu điều này không được, hãy tham khảo câu trả lời hoặc bài đăng này để gỡ lỗi nó.

bỏ chọn tự động kiểm tra trên bản xem trước safari


0

Trong Xcode, nhấp vào bên trái của số dòng để đặt điểm ngắt. Sau đó, bạn có thể khởi chạy nó bằng cách thực hiện "Xây dựng và gỡ lỗi".

Bạn không nên có đối tượng mà bạn tạo autoreleasevì bộ nhớ là một mặt hàng trên iPhone. Apple khuyến nghị gọi một cách rõ ràng release.


0

Để tìm những loại vấn đề về bộ nhớ và con trỏ nói chung, bạn muốn chạy mã của mình với trình kiểm tra lỗi bộ nhớ thời gian chạy như Valgrind . Điều này sẽ có thể chỉ ra nhiều thứ mà mã của bạn đang làm sai, ngoài những thứ khiến nó gặp sự cố.

Valgrind có thể hoạt động trên OSX (mặc dù nó nói rằng nó "không được hỗ trợ và không hoàn chỉnh và có lỗi") và với một chút hack, ai đó đã làm cho nó hoạt động trên các tệp thực thi SDK iPhone .

Tốt hơn nữa, bạn có thể thử Instruments, là một phần của XCode. Có một hướng dẫn để chạy nó ở đây .


1
nhạc cụ là con đường để đi; sử dụng công cụ phân bổ đối tượng và bật zombie. (hoặc chỉ sử dụng mẫu Zombies). Valgrind là giải pháp cuối cùng. Nó rất chậm và thường không hoạt động.
bbum

0

Nếu malloc_error_breakkhông giúp ...

Cách tốt nhất để giải quyết lỗi này là chạy các nhạc cụ với chế độ NSZombiesbật. Các công cụ sẽ gắn cờ cho bạn khi Zombie bị đánh lừa và bạn có thể theo dõi trực tiếp lại dòng mã.

Snow Leopard được yêu cầu, đó là một chiếc phao cứu sinh!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.