2010-09-01 13 views
12

Trong thử nghiệm, tôi loại bỏ mọi thứ từ stderr vì nó cắt đầu ra của vỏ kiểm tra. Tôi đang sử dụng đoạn mã sau:Truyền để hủy không xóa lỗi warn_unused_result

freopen("/dev/null", "w", stderr); 

Khi biên dịch với -Wall -Werror, tôi nhận được lỗi

error: ignoring return value of ‘freopen’, declared with attribute warn_unused_result 

được mong đợi. Tuy nhiên, các giải pháp thông thường của đúc để void dường như không hoạt động. Tức là, thay đổi mã thành

vẫn tạo ra cảnh báo tương tự. Tôi không quan tâm nếu chức năng này thất bại vì kịch bản trường hợp xấu nhất là một chút đầu ra thêm. Bất kỳ cách nào khác tôi có thể sửa lỗi này?

EDIT: Tôi biết tôi có thể giới thiệu một biến không cần thiết bổ sung. Tôi thực sự muốn biết tại sao đúc để void không hoạt động.

UPDATE: tôi quyết định đi với điều này:

FILE *null = fopen("/dev/null", "w"); 
if (null) { fclose(stderr); stderr = null; } 

Sau khi đọc các tài liệu hướng dẫn freopen cẩn thận hơn, tôi thấy rằng nếu mở /dev/null thất bại, stderr sẽ vẫn bị phá hủy. Điều này giải quyết vấn đề đó.

+4

'null' là một tên xấu cho một biến C . –

+0

Điểm tốt. Tôi không biết tôi nghĩ đó là một ý tưởng hay. –

Trả lời

6

Tại sao không đơn giản sử dụng kết quả, như cảnh báo su ggests bạn nên.

if (freopen("/dev/null", "w", stderr) == 0) 
    ...oops...lost stderr...hard to report errors... 

Vì hàm được khai báo với thuộc tính 'warn_unused_result', bạn sẽ nhận được cảnh báo trừ khi bạn sử dụng giá trị trả về. Vì hàm trả về null trên thất bại hoặc đối số luồng tệp thành công, bạn có thể nghĩ đến việc gán kết quả. Tuy nhiên, bạn không nên assign để thiết bị lỗi chuẩn như thế (xem dưới đây), vì vậy đây là một ý tưởng tồi:

stderr = freopen("/dev/null", "w", stderr); 

Về mặt lý thuyết, bạn nên thực hiện kiểm tra đó; có những trường hợp thảm khốc (và không hợp lý) mà bạn không thể mở "/ dev/null".


Footnote 229 trong tiêu chuẩn C99 ghi chú:

229) Việc sử dụng chính của freopen chức năng là thay đổi tập tin liên kết với một dòng văn bản chuẩn (stderr, stdin, hoặc stdout), vì các số nhận dạng đó không cần phải có các giá trị có thể sửa đổi mà giá trị được trả về bởi hàm fopen có thể được chỉ định.

Do đó, bài tập không được thông báo. Nhưng việc kiểm tra giá trị trả về sẽ đối phó với cảnh báo trình biên dịch và có thể giúp ngăn chặn các bãi lõi. Nó không chắc chắn để cải thiện con số bảo hiểm mã của bạn, mặc dù (con đường lỗi sẽ không được thực hiện rất thường xuyên, nó sẽ được khó khăn để buộc bảo hiểm của việc xử lý lỗi). Lưu ý rằng mô tả POSIX của freopen() có một số nhận xét vừa phải ăn da về thiết kế freopen(), được phát minh bởi ủy ban tiêu chuẩn C (phiên bản 1989), có lẽ không có đầu vào từ POSIX.

+0

Cảm ơn. Bạn làm cho một điểm tốt. –

2
int tossmeout = freopen("/dev/null", "w", stderr); 

Như ý kiến ​​dưới đây thử

FILE *tossmeout = freopen("/dev/null", "w", stderr); 

(void *)freopen("/dev/null", "w", stderr); 
+1

Chắc chắn. Nhưng có cách nào để làm điều này mà không tạo ra một biến không cần thiết? –

+0

Ngoài ra, 'freopen' trả về' FILE * '. – dreamlax

+0

@Michael: hầu hết các trình biên dịch sẽ không "tạo" một biến - chúng chỉ cần đặt nó vào một bảng biểu tượng và chỉ đặt chỗ cho nó nếu nó được tham chiếu. - họ * có thể * được lười biếng tăng con trỏ ngăn xếp cho lưu trữ địa phương. – Hogan

11

Một nặng ít trên các phần mở rộng GCC, nhưng các biến không có bên ngoài có thể nhìn thấy:

#define ignore_result(x) ({ typeof(x) z = x; (void)sizeof z; }) 
ignore_result(freopen("/dev/null", "w", stderr)); 
+0

Tôi sẽ đề nghị sử dụng __typeof __() thay cho typeof(). –

2

Nếu bạn thực sự phải sử dụng ngôn ngữ C (không phải C++) thì bạn có thể sử dụng workaround này:

inline void ignore_result_helper(int __attribute__((unused)) dummy, ...) 
{ 
} 

#define IGNORE_RESULT(X) ignore_result_helper(0, (X)) 

Ví dụ

typedef struct A 
{ 
    int x; 
} A; 

__attribute__((warn_unused_result)) A GetA() 
{ 
    A const a; 
    return a; 
} 

int main() 
{ 
    IGNORE_RESULT(GetA()); 
    return 0; 
} 
+4

Tôi không * có * để sử dụng C, nhưng tôi thích C to C++ :) –

+0

Tôi ước rằng tôi có thể upvote rằng bình luận nhiều hơn một lần ;-) – Mawg