2011-02-21 24 views
6

Khá nhiều người dường như sử dụng một macro nhưChúng ta có thực sự cần một macro phát hành an toàn không?

#define SAFE_RELEASE(X) [X release]; X = nil; 

(trong đó có tôi).

Tôi đã đánh giá lại lý do tại sao tôi đang sử dụng nó và muốn đặt một số ý kiến.

Mục đích (tôi nghĩ) để sử dụng macro này là để nếu bạn đã vô tình sử dụng đối tượng của bạn sau khi phát hành nó thì bạn sẽ không có được một ngoại lệ truy cập xấu vì Objective-C sẽ khá vui vẻ bỏ qua nó khi đối tượng là nil.

Tôi cho rằng điều này có khả năng che giấu một số lỗi không rõ ràng. Có lẽ nó sẽ thực sự là thích hợp hơn cho chương trình sụp đổ khi bạn cố gắng sử dụng X một lần nữa. Bằng cách đó trong quá trình thử nghiệm, bạn có thể tìm thấy vấn đề và cải thiện mã.

Macro này có khuyến khích lập trình lười biếng không?

Suy nghĩ?

+1

Phần có liên quan trong [FAQ] (http://stackoverflow.com/faq) cho các câu hỏi không nên hỏi ở đây. - 'Không có vấn đề thực tế cần được giải quyết: "Tôi tò mò nếu người khác cảm thấy như tôi."' – Abizern

+0

Đủ công bằng, nhưng đó là vấn đề tôi đang gặp phải. Vấn đề là tôi có nên tiếp tục sử dụng macro này không? Có lý do chính đáng nào để sử dụng nó mà tôi không biết? – Ian1971

Trả lời

6

Tôi nghĩ bạn thảo luận tất cả những ưu và khuyết điểm trong câu hỏi của bạn, vì vậy tôi không có số tiền lớn để thêm vào. Cá nhân tôi không sử dụng cấu trúc. Như bạn đề xuất, nó có thể được sử dụng để in trên các khu vực mà mọi người không hiểu chính xác việc quản lý bộ nhớ. Sở thích của tôi là sửa lỗi và không phải là triệu chứng.

Tuy nhiên, một sự thỏa hiệp mà tôi đã nhìn thấy từ bất cứ lúc nào là:

  • Làm cho nó sụp đổ trong phát triển
  • Làm var = nil; trong mã sản xuất

Bằng cách đó nó sức đáng tin cậy hơn với khách hàng trả tiền và vẫn bị treo sớm trong quá trình phát triển.

Tôi cũng không quan tâm đến điều này vì bạn đang sử dụng mã khác cho người dùng của mình và chỉ vì phiên bản lỗi tiếp tục chạy không có nghĩa là nó đang hoạt động đúng. Không bị lỗi nhưng làm hỏng cơ sở dữ liệu của bạn không phải là hành vi mong muốn ...

+0

Tôi đồng ý rằng tôi không thích có mã số khác nhau về sản xuất – Ian1971

+0

Tại sao bỏ phiếu xuống? –

1

Bạn không cần nó, nhưng thật thuận tiện để có. Tôi sử dụng một cái gì đó tương tự trong các ứng dụng của tôi. Bạn có thể coi nó là "lười biếng", nhưng khi bạn có một nơi nào đó khoảng 20 đối tượng, hãy viết những thứ này bằng tay một cách thủ công.

+1

Tôi đoán nó không phải là quá nhiều về vĩ mô mỗi se nhưng về lý thuyết của thiết lập một đối tượng để nil sau khi bạn phát hành nó. Nếu bạn làm xong với đối tượng thì có lẽ bạn không nên cố gắng truy cập lại nó, và nếu bạn truy cập lại nó thì có thể tốt nhất là có sự cố để bạn có thể phân loại vấn đề mã cụ thể đó. tức là tại sao bạn lại cố truy cập lại? – Ian1971

2

Tôi nghĩ rằng nó hoặc tương đương như self.myVar = nil nếu có, là tốt. Có rất nhiều trường hợp bạn chỉ đơn giản là không thể chỉ định nil và giả sử bất kỳ truy cập sau này là một lỗi.

Ví dụ ở UIKit, bạn nên giải phóng càng nhiều tài nguyên càng tốt khi hệ điều hành hỏi. Ví dụ.

- (void)didReceiveMemoryWarning 
{ 
    [myCachedData release]; 
    [super didReceiveMemoryWarning]; 
} 

Bây giờ, khi lớp học của tôi tiếp theo được sử dụng làm cách nào để biết rằng myCachedData giờ đây không hợp lệ? Cách duy nhất (ngắn có ANOTHER biến hoạt động như một lá cờ) là để thiết lập myCachedData đến nil sau khi phát hành nó. Và ngưng tụ hai dòng tẻ nhạt đó thành một trong những thứ chính xác là SAFE_RELEASE.

+0

Tôi nghĩ rằng bạn là đúng, nó là chính xác để thiết lập để nil khi áp dụng. Tôi nghĩ rằng cái bẫy tôi rơi vào bị mù quáng bằng cách sử dụng vĩ mô và không nghĩ về nó quá nhiều. – Ian1971

1

Tôi đang xem xét cùng một câu hỏi.Với chút đọc, tôi đã có một cái gì đó như thế này:

#define DEBUGGING 
    //#define PRODUCTION 

#ifdef DEBUGGING 
#define SAFE_RELEASE(X) [X release]; 
#else 
#define SAFE_RELEASE(X) [X release]; X = nil; 
#endif 

Vì vậy theo cách đó nếu tôi đang phát triển, tôi gặp sự cố. Trong sản xuất tôi không.

Scott < -

+0

Điều này có thể dẫn đến rất khó để theo dõi lỗi trong sản xuất - xem câu trả lời của tôi để biết chi tiết. – Sebastian

1

Như Andrew chỉ ra, có những trường hợp giao nil không chỉ tránh lỗi, nhưng cần thiết. Chỉ cần xem xét đặc trưng UIViewController đang

- (void)viewDidLoad { 
    button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // autoreleased 
    [button retain]; // keep alive 
} 

- (void)viewDidUnload { // view has been removed 
    [button release]; 
} 

- (void)dealloc {  // destroying the view controller 
    [button release]; // <-- problem 
} 

Trong trường hợp bộ điều khiển được nạp, sau đó bốc dỡ (vì một bộ điều khiển xem sẽ được hiển thị một ký ức đang ở mức thấp) và cuối cùng bị phá hủy, [button release] trong dealloc sẽ quá thả nút (gửi một thông báo cho một đối tượng được phát hành). Vì vậy, nó là cần thiết để gán nil. Giải pháp an toàn sẽ là:

- (void)viewDidUnload { // view has been removed 
    [button release]; 
    button = nil; 
} 

- (void)dealloc {  // destroying the view controller 
    [button release]; // <-- safe 
} 

Đối với những trường hợp macro là tốt đẹp và hữu ích. Để rõ ràng hơn về điều đó, hãy đặt tên nó là RELEASE_AND_NIL

#define RELEASE_AND_NIL(X) [X release]; X = nil; 
Các vấn đề liên quan