2009-10-03 14 views
12

Trình biên dịch MSVC nói rằng fopen() không được dùng nữa và khuyên bạn nên sử dụng fopen_s().Có cách nào để sử dụng fopen_s() với GCC hoặc ít nhất tạo ra một #define về nó?

Có cách nào để sử dụng fopen_s() và vẫn có thể di chuyển không?

Bất kỳ ý tưởng nào cho một số #define?

+0

Một vấn đề tương tự [ở đây] (http://stackoverflow.com/questions/14386/fopen-deprecated-warning). – luvieere

Trả lời

23

Chức năng *_s của Microsoft không thể chuyển đổi, tôi thường sử dụng các hàm C89/C99 tương đương và tắt cảnh báo không dùng nữa (#define _CRT_SECURE_NO_DEPRECATE).

Nếu bạn nhấn mạnh, bạn có thể sử dụng một chức năng tiếp hợp (không nhất thiết là một vĩ mô!) Mà các đại biểu fopen() trên nền tảng mà không có fopen_s(), nhưng bạn phải cẩn thận để ánh xạ giá trị của errno_t mã trở lại từ errno.

errno_t fopen_s(FILE **f, const char *name, const char *mode) { 
    errno_t ret = 0; 
    assert(f); 
    *f = fopen(name, mode); 
    /* Can't be sure about 1-to-1 mapping of errno and MS' errno_t */ 
    if (!*f) 
     ret = errno; 
    return ret; 
} 

Tuy nhiên, tôi không thấy như thế nào fopen_s() là bất kỳ an toàn hơn fopen(), vì vậy tôi thường đi cho tính di động.

+5

Microsoft LOVES tạo ra phiên bản của riêng họ về mọi thứ. Tôi tự hỏi tại sao ... – LiraNuna

+9

Điều thú vị là, chúng bây giờ là một phần của C11 (mặc dù trong Phụ lục K) – rubenvb

+0

Tốt hơn nhiều so với phương pháp tiếp cận macro thuần túy của tôi (bây giờ là cũ, không phải tôi cần nó nữa).Cách tiếp cận hàm của bạn tái tạo một phần hành vi fopen_s trên thất bại bằng cách trả về errno (= EINVAL, tức là 22, fwiw). Bạn cũng có thể tạo ra * ngoại lệ tham số không hợp lệ * để phù hợp với hành vi fopen_s chặt chẽ hơn. – riderBill

4

Trong C/C++,

#ifdef __unix 
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL 
#endif 

Trong Makefile

CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL' 

Chú ý rằng thành công fopen_s trở về 0 khi fopen trả về một con trỏ tập tin khác không. Vì vậy nó là cần thiết để thêm "== NULL" vào cuối của vĩ mô, ví dụ:

if (fopen_s(&pFile,filename,"r")) perror("cannot open file"); 
1

Nhiều chức năng bảo mật của Microsoft được bao gồm trong Phụ lục K của tiêu chuẩn C11, nhưng nó không được hỗ trợ rộng rãi, vì vậy tính di động vẫn là một vấn đề. Có một nhu cầu về sự an toàn được cải thiện trong một số ứng dụng; có lẽ sự hỗ trợ sẽ cải thiện trong tương lai.

Tôi quá khứ, tôi đã làm điều đó như thế này:

#define fopen_s(fp, fmt, mode)   *(fp)=fopen((fmt), (mode)) 

vĩ mô là đơn giản và thẳng về phía trước, đủ tốt cho một cái gì đó nhanh chóng và dơ bẩn, nhưng nó không cung cấp cho hành vi ngoại trừ fopen_s, và nó sẽ không cung cấp tính bảo mật của hàm fopen_s thực.

Cách tiếp cận chức năng của @Alex B ở trên một phần tái tạo hành vi thích hợp về lỗi; anh ta trả về errno (= EINVAL). Cách tiếp cận của ông có thể được mở rộng hơn nữa bằng cách tạo ra một ngoại lệ tham số không hợp lệ để tái tạo đầy đủ hơn hành vi của fopen_s.

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