2013-08-21 31 views
5

Tôi đang viết chương trình trong đó hầu hết các chức năng thư viện được sử dụng trả lại -1 về lỗi và đặt errno. Hành vi của chương trình là như vậy mà nó thoát nếu lỗi xảy ra. Để xác định điểm xuất cảnh chính xác và lỗi từ bên ngoài chương trình (ví dụ sử dụng gdb), tôi muốn sử dụng phương pháp sau đây:Có an toàn để giả định không phải là luôn luôn tích cực?

err = func_1(..arglist_1..); 
if(err != 0) 
{ 
    perror("func(..arglist..)"); 
    return ((1u << 8) | errno); 
} 
//.. 
//.. some more funcs 
//.. 
err = func_n(..arglist_n..); 
if(err != 0) 
{ 
    perror("func(..arglist_n..)"); 
    return (((unsigned)n << 8) | errno); 
} 

Vấn đề ở đây là giả định an toàn.

Reality:errno được khai báo là extern int errno; bên errno.h
Assumption 1: Giá trị củaerrno luôn nhỏ hơn 255.
Assumption 2:errno luôn là tích cực.

Trên cơ sở tất cả các hằng số lỗi (EAGAIN, v.v.) được xác định trong errno.h, các giả định này là đúng hiện tại. Những điều này có thể được giả định là đúng trong tương lai không?

P .: Tôi không muốn phụ thuộc vào perror() để xác định điểm thoát.

+0

Tôi nghi ngờ giả định là an toàn. Đối với cái thứ hai, bạn có xem là '0' dương? – jxh

+0

Không có '0' bị loại trừ dưới dạng [liên kết này tại đây] (http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html) nói:' Không có chức năng nào trong khối lượng IEEE Std 1003.1-2001 này phải được đặt errno to 0.' –

+2

Chỉ vì không có hàm nào trong thư viện chuẩn đặt nó thành '0' không có nghĩa là ai đó không đặt nó thành' 0'. Đối với một số chức năng thư viện chuẩn, cách duy nhất để xác định xem cuộc gọi có thất bại hay không trước tiên đặt 'errno' thành' 0' và sau đó xem hàm nào thực hiện. – jxh

Trả lời

12

Trạng thái thoát của chương trình của bạn bị giới hạn ở 0..255, vì vậy nếu các báo cáo trả về đó từ chương trình main(), các bit thứ tự cao không liên quan.

Các tiêu chuẩn C (ISO/IEC 9899: 2011 §7.5 lỗi <errno.h>) nói:

errno
mà mở rộng đến một giá trị trái modifiable 201) đã gõ int và sợi local storage thời gian , giá trị được đặt thành một số lỗi dương bởi một số hàm thư viện.

201) Macro errno không cần phải là số nhận dạng của đối tượng. Nó có thể mở rộng thành giá trị sửa đổi do một cuộc gọi hàm (ví dụ: *errno()).

Chuẩn C dự kiến ​​lỗi sẽ dương. POSIX (IEEE Std 1003.1 2013 Edition) khẳng định cho <errno.h>:

Tiêu đề <errno.h> quy định các macro sau đó sẽ mở rộng để nguyên biểu thức thường xuyên với loại int, các giá trị tích cực riêng biệt (ngoại trừ được nêu dưới đây), và đó phải phù hợp để sử dụng trong #if chỉ thị tiền xử lý: ...

vì vậy, bạn có thể một cách hợp lý một cách an toàn cho rằng (hệ thống tạo) số lỗi là tích cực, nhưng mã của bạn có thể thiết lập errno tiêu cực (hoặc không có). Hiện tại, không có hệ thống POSIX nào tạo ra số lỗi cao hơn một nơi nào đó dưới 200, vì vậy giả sử chúng sẽ bị giới hạn ở 255 là an toàn trong ngắn hạn nhưng có lẽ không phải trong dài hạn. Không có lý do tại sao họ nên rất hạn chế.

'Thực tế' được xác nhận quyền sở hữu của bạn chỉ áp dụng cho các chương trình không phải là luồng. Nếu bạn đang biên soạn cho hỗ trợ luồng, thì errno không chỉ được khai báo là extern int errno; và trong mọi trường hợp bạn không nên cố gắng khai báo errno cho chính mình. Chỉ chỉ cách an toàn để khai báo là qua tiêu đề <errno.h>.

+0

Ok, tôi đã nhận được câu trả lời của tôi, cảm ơn Jonathan Leffler. Trước hết, anh ấy đúng, tôi dự định làm điều này trong main(). Tiếp theo, sai lầm của tôi tôi đã quên về các chương trình đa luồng. Ngoài ra tôi đã sử dụng [bản sao cũ của tiêu chuẩn] (http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html) để tham khảo, ở đó nó không đề cập rằng nó sẽ luôn luôn là tích cực. –

+1

C89 không quy định rằng số lỗi là số dương (chỉ khác 0); C99 đã quy định rằng số lỗi là dương. Điều thú vị là, POSIX 1997 cho biết "Tiêu đề' 'cung cấp một khai báo cho errno và cho các giá trị khác 0 cho các hằng số ký hiệu sau đây." phù hợp với tiêu chuẩn C89 (C90) sau đó. –

+0

@nishant: thú vị - bạn liên kết đến trang POSIX 2004 cho 'errno', không đề cập đến 'tích cực' (và trang POSIX 2013 cho [' errno'] (http: //pubs.opengroup. org/onlinepubs/9699919799/functions/errno.html)), trong khi tôi liên kết với trang POSIX (2013) cho ' ', nó đề cập đến nó (cũng như trang POSIX 2004 cho tiêu đề). Tôi đoán tôi đã may mắn chọn đúng nơi để xem; Tôi đã không nhận thức được sự bất đối xứng. –

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