2009-07-16 37 views
19

Có một lý do tại sao CFRelease không kiểm tra NULL? Không phải là nó không thể chấp nhận được khi [nil release]; miễn phí (NULL); xóa NULL; tất cả các công việc hoàn toàn tốt đẹp?Tại sao tai nạn CFRelease (NULL)?

Trả lời

27

Mã nguồn cho CoreFoundation có sẵn công khai. Cụ thể, đối Snow Leopard mã để CFRelease là trong http://www.opensource.apple.com/source/CF/CF-550/CFRuntime.c

Dưới đây là những gì các phần có liên quan trông giống như:

void CFRelease(CFTypeRef cf) { 
    if (NULL == cf) HALT; 
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED 
    if (CF_IS_COLLECTABLE(cf)) { 
     if (CFTYPE_IS_OBJC(cf)) { 
      // release the GC-visible reference. 
      auto_zone_release(auto_zone(), (void*)cf); 
     } else { 
      // special-case CF objects for better performance. 
      _CFRelease(cf); 
     } 
     return; 
    } 
#endif 
} 

này không trả lời câu hỏi của bạn về động cơ thiết kế, nhưng bạn cũng được hỏi tại sao không CFRelease không kiểm tra NULL. Nó kiểm tra và không thành công khi NULL được chuyển thành tham số.

Niềm tin cá nhân của tôi tương tự như của Quinn- rằng các nhà thiết kế CF cảm thấy đó là lỗi lập trình để chuyển sang NULL.

7

Tất cả các chức năng này là một phần của các API khác nhau mà theo quy ước khác nhau liên quan đến xử lý NULL:

  1. CFRelease là một phần của SDK CoreFoundation C, mà không chấp nhận NULL tài liệu tham khảo như các đối số theo mặc định.
  2. [nil release] sử dụng Objective-C (cho phép dereferences của nil)
  3. free(NULL) là một phần của thư viện C (libc) mà cho phép NULL luận
  4. delete NULL là một phần của ++ thư viện C (libc++) mà cho phép NULL luận

Tôi đoán là CoreFoundation Nhà văn SDK đã quyết định nhất quán hơn với phần còn lại của SDK thay vì có chức năng tương tự trong các SDK khác.

+2

Với tôi, câu trả lời này khá nhiều nói: CFRelease bị treo vì CF hoạt động theo cách đó. miễn phí (NULL) không sụp đổ vì tiêu chuẩn C nói như vậy. xóa NULL không sụp đổ vì C + + tiêu chuẩn nói như vậy. Nó không trả lời câu hỏi của tôi. Tôi hỏi tại sao nhà thiết kế SDK CF cố tình quyết định chỉ cho phép các API công khai của họ phá vỡ chương trình. –

+0

Nếu không yêu cầu một nhà thiết kế CF trực tiếp (giả sử họ có thể/sẽ cho bạn biết lý do tại sao) chúng tôi chỉ đang suy đoán. Tôi đã đưa ra dự đoán tốt nhất của tôi trong câu trả lời của tôi. –

+0

Nếu bạn đang đặt câu hỏi chỉ có thể được trả lời bởi người đã viết API này, tại sao yêu cầu SO? Điểm của SO là đặt các câu hỏi mà cộng đồng chịu trách nhiệm. – smorgan

9

Điểm tốt, dường như nó không có ý nghĩa gì nhiều trong nháy mắt đầu tiên. Tất nhiên, các behavior is properly documented, nhưng nó sẽ được tốt đẹp nếu nó có thể xử lý NULL một cách duyên dáng. Lưu ý rằng CFRetainCFMakeCollectable (mới trong 10.4, GC được bật trong 10.5) thể hiện cùng một hành vi. Tôi không thuộc về tất cả các động lực để thiết kế nó theo cách đó, nhưng sự nhấn mạnh có lẽ là nhiều hơn về tính nhất quán nội bộ với phần còn lại của khung CoreFoundation.

Rất khó hiểu/không thể biết được lý do tại sao CF được thiết kế theo cách đó trừ khi bạn có thể hỏi một trong các nhà thiết kế. Đoán tốt nhất của tôi là các nhà thiết kế đã quyết định rằng việc chuyển giao NULL cho các chức năng quản lý bộ nhớ là (phải là?) Một lỗi lập trình. Người ta có thể tranh luận rằng việc gây ra sự cố trên NULL là một hành vi "không nhanh" mong muốn, vì các lỗi xảy ra gần như ngay lập tức dễ dàng theo dõi hơn các lỗi mà không làm gì thay vì những gì bạn mong đợi. Cá nhân, tôi thích cách tiếp cận không-không-trên-null, nhưng tôi đoán đó là cuộc sống ...

Do API không thể/sẽ không thay đổi, bạn có thể kiểm tra NULL hoặc khắc phục sự cố trường hợp. Một tùy chọn có thể là định nghĩa một hàm nội tuyến hoặc macro chỉ gọi CFRelease cho các tham chiếu không NULL. Trong bất kỳ trường hợp nào, có thể tốt nhất là phải rõ ràng trong mã của bạn để tránh nhầm lẫn xuống đường.

+4

Hãy xem xét rằng Quartz CGImageRelease và similars chấp nhận NULL: "Hàm này tương đương với CFRelease, ngoại trừ việc nó không gây ra lỗi nếu tham số hình ảnh là NULL." – IlDan

+0

Phải, nó sẽ tốt đẹp, nhưng đó là trong CoreGraphics, không phải Core Foundation. Nếu CFRelease và bạn bè bị thay đổi thành ** not ** crash khi trao NULL, nó có thể gây ra kết quả không mong muốn trong mã hiện tại (mặc dù hy vọng không ai cố ý gây ra sự cố theo cách này) và gây nhầm lẫn cho các lập trình viên CoreFoundation. Mặc dù vậy, tôi có xu hướng đồng ý với bạn. –

2

Bạn có thể xem mã nguồn của CFReleaseProtector để xử lý (hoặc hiểu rõ hơn) vấn đề này.

CFRelease không sụp đổ trên NULL,

http://unsanity.org/archives/haxies/cfrelease_no_mo.php

Bạn có thể giải nén CFReleaseProtector.sit với công cụ unar dòng lệnh (một phần của The Unarchiver, xem danh sách mã tải Google của nó).

+0

Vẫn gặp sự cố (iOS 9). –

Các vấn đề liên quan