2008-08-18 64 views
52

Trên Visual Studio 2005 Trình biên dịch C++, tôi nhận được cảnh báo sau khi mã của tôi sử dụng số fopen và các cuộc gọi như vậy.fopen cảnh báo không được chấp nhận

1>foo.cpp(5) : warning C4996: 'fopen' was declared deprecated 
1>  c:\program files\microsoft visual studio 8\vc\include\stdio.h(234) : see declaration of 'fopen' 
1>  Message: 'This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.' 

Làm cách nào để ngăn chặn điều này?

Trả lời

97

Có vẻ như Microsoft đã không dùng nhiều cuộc gọi sử dụng bộ đệm để cải thiện bảo mật mã. Tuy nhiên, các giải pháp mà họ đang cung cấp không phải là di động. Dù sao, nếu bạn không quan tâm đến việc sử dụng phiên bản bảo mật của cuộc gọi (như fopen_s), bạn cần đặt định nghĩa _CRT_SECURE_NO_DEPRECATE trước các tệp tiêu đề được bao gồm. Ví dụ:

#define _CRT_SECURE_NO_DEPRECATE 
#include <stdio.h> 

Chỉ thị tiền xử lý cũng có thể được thêm vào cài đặt dự án của bạn để thực hiện nó trên tất cả các tệp trong dự án. Để thực hiện việc này, hãy thêm _CRT_SECURE_NO_DEPRECATE đến Thuộc tính dự án -> Thuộc tính cấu hình -> C/C++ -> Preprocessor -> Định nghĩa tiền xử lý.

+8

Bạn có lẽ nên làm một cái gì đó giống như mặc dù điều này: #ifdef _WIN32 #define _CRT_SECURE_NO_DEPRECATE #endif #include Bởi vì các nền tảng khác không cần điều đó được xác định trong thời gian biên dịch. – markwatson

+2

Có thực sự làm việc. –

+1

@markwatson Bảo vệ tốt hơn là kiểm tra '#ifdef _MSC_VER'. – MicroVirus

23

Vâng, bạn có thể thêm một:

#pragma warning (disable : 4996) 

trước khi sử dụng fopen, nhưng có bạn xem là sử dụng fopen_s như cảnh báo cho thấy? Nó trả về một mã lỗi cho phép bạn kiểm tra kết quả của cuộc gọi hàm.

Sự cố với việc tắt cảnh báo chức năng không dùng nữa là Microsoft có thể xóa chức năng được đề cập trong phiên bản sau của CRT, vi phạm mã của bạn (như đã nêu bên dưới trong nhận xét, điều này sẽ không xảy ra trong trường hợp này với fopen bởi vì nó là một phần của tiêu chuẩn C & C++ ISO).

+31

"Microsoft có thể xóa chức năng được đề cập trong phiên bản sau của CRT" - nếu họ không muốn triển khai tiêu chuẩn C hoặc C++ nữa. –

+3

Một số người cũng nhắm mục tiêu nền tảng không phải MS. Và với rất nhiều hàm số _s này, không thực sự là một lợi ích bảo mật đáng chú ý. – sstn

+8

Đối với các nhà cung cấp dịch vụ tương lai: 'Trong ngữ cảnh này," không dùng nữa "chỉ có nghĩa là việc sử dụng chức năng không được khuyến nghị; nó không chỉ ra rằng hàm được lên lịch để xóa khỏi CRT.' - [msdn] (http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx) ++++ – Navin

4

Cân nhắc sử dụng thư viện di động như glib hoặc apache portable runtime. Chúng thường cung cấp các lựa chọn thay thế an toàn, di động cho các cuộc gọi như thế này. Đó cũng là một điều tốt, bởi vì những cuộc gọi không an toàn này không được chấp nhận trong hầu hết các môi trường hiện đại.

11

Đây chỉ là Microsoft đang táo bạo. "Không được chấp nhận" ngụ ý một tính năng ngôn ngữ có thể không được cung cấp trong các phiên bản tương lai của các thư viện chuẩn/ngôn ngữ tiêu chuẩn, theo quyết định của ủy ban tiêu chuẩn. Nó không, hoặc không nên có nghĩa là, "chúng tôi, đơn phương, không nghĩ rằng bạn nên sử dụng nó", không có vấn đề như thế nào được thành lập mà lời khuyên là.

+14

Ý nghĩa của từ tiếng Anh "phản đối" chính là điều thứ hai: "chúng tôi nghĩ bạn không nên sử dụng nó". Nhưng trong cách nói máy tính gần đây nó có ý nghĩa yếu hơn, "nó có thể không khôn ngoan để sử dụng nó, bởi vì chúng ta đang loại bỏ nó, và chúng tôi đã cung cấp một cái gì đó mà chúng tôi nghĩ là tốt hơn". –

7

Nếu bạn đang có ý định cho một hệ điều hành khác nhau (như Mac OS     X, Linux), bạn có thể sử dụng như sau:

#ifdef _WIN32 
#define _CRT_SECURE_NO_DEPRECATE 
#endif 
0

Tôi cũng có cùng một vấn đề. Khi tôi cố gắng thêm thư viện opencv

#include <opencv\cv.h> 

Tôi không nhận được cảnh báo mà là lỗi.

error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\program files (x86)\opencv\build\include\opencv2\flann\logger.h 

Tôi cũng đã sử dụng các chỉ thị tiền xử lý như đã đề cập. Nhưng điều đó không giải quyết được vấn đề.

tôi giải quyết nó bằng cách làm như sau:

  • Đến Properties -> C/C++ -> precompiled Headers -> Chọn Không Dùng precompiled Headers trong precompiled Header.
1

Nếu bạn muốn nó được sử dụng trên nhiều nền tảng, bạn như có thể nhận xét sử dụng định nghĩa như:

#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ 
         || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) 

     errno_t err = fopen_s(&stream,name, "w"); 

#endif 

#if defined(unix)  || defined(__unix)  || defined(__unix__) \ 
         || defined(linux)  || defined(__linux)  || defined(__linux__) \ 
         || defined(sun)   || defined(__sun) \ 
         || defined(BSD)   || defined(__OpenBSD__) || defined(__NetBSD__) \ 
         || defined(__FreeBSD__) || defined __DragonFly__ \ 
         || defined(sgi)   || defined(__sgi) \ 
         || defined(__MACOSX__) || defined(__APPLE__) \ 
         || defined(__CYGWIN__) 

     stream = fopen(name, "w"); 

#endif 
+0

#IF phức tạp của bạn chỉ giải quyết các nền tảng chứ không phải các phiên bản trình biên dịch. Làm thế nào về '#if (được xác định (_MSC_VER) && (_MSC_VER> = 1600)) ... #ELSE ...' Điều đó sẽ bao gồm tất cả các trường hợp, phải không? – riderBill

+0

_MSC_VER = 1600 có thể không phải là phiên bản đầu tiên không dùng nữa fopen(), v.v. Đây là phiên bản đầu tiên mà tôi gặp sự cố. – riderBill

+0

Hình như phiên bản đầu tiên của MSVC với (một số) các chức năng an toàn là 2005, _MSC_VER = 1400. – riderBill

1

Nhiều người trong số các chức năng an toàn của Microsoft, bao gồm fopen_s(), là một phần của C11, vì vậy họ nên được di động ngay bây giờ. Bạn nên nhận ra rằng các hàm an toàn khác nhau trong các hành vi ngoại lệ và đôi khi trong các giá trị trả về. Ngoài ra, bạn cần lưu ý rằng mặc dù các chức năng này được chuẩn hóa, đó là một phần tùy chọn tùy chọn của tiêu chuẩn (Phụ lục K) ít nhất glibc (mặc định trên Linux) và libc của FreeBSD không thực hiện.

Tuy nhiên, tôi đã chiến đấu vấn đề này trong một vài năm. Tôi gửi một tập lớn các macro chuyển đổi here., Đối với vấn đề trước mắt của bạn, hãy đặt đoạn mã sau vào một tập tin bao gồm, và bao gồm nó trong mã nguồn của bạn:

#pragma once 
#if !defined(FCN_S_MACROS_H) 
    #define FCN_S_MACROS_H 

    #include <cstdio> 
    #include <string> // Need this for _stricmp 
    using namespace std; 

    // _MSC_VER = 1400 is MSVC 2005. _MSC_VER = 1600 (MSVC 2010) was the current 
    // value when I wrote (some of) these macros. 

    #if (defined(_MSC_VER) && (_MSC_VER >= 1400)) 

     inline extern 
     FILE* fcnSMacro_fopen_s(char *fname, char *mode) 
     { FILE *fptr; 
     fopen_s(&fptr, fname, mode); 
     return fptr; 
     } 
     #define fopen(fname, mode)   fcnSMacro_fopen_s((fname), (mode)) 

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

    #endif //_MSC_VER 

#endif // FCN_S_MACROS_H 

Tất nhiên phương pháp này không thực hiện hành vi ngoại lệ dự kiến .

+0

MS '_s' không giống với giao diện kiểm tra giới hạn C11 nói chung. Một số có cùng tội lỗi, một số thì không. Vì giao diện đó là tùy chọn, nên ít triển khai hỗ trợ nó, bercause nó hầu như không cần thiết. Và mã của bạn là C++, không phải C mà bạn tham chiếu trong văn bản. – Olaf

+0

@Olaf: Hmm. Tôi không thể giải quyết việc kiểm tra giới hạn, khác hơn là chỉ ra hành vi ngoại lệ của tôi báo trước. – riderBill

+0

Bạn nói đúng rằng tôi đã trích dẫn tiêu chuẩn C11 (trái với C++ 14 hoặc 17). Các chức năng có sẵn trong các phiên bản gần đây của trình biên dịch C++ của Microsoft. Nó chỉ ra rằng Phụ lục K không được hỗ trợ rộng rãi bên ngoài MSVS. Jonathan Leffler đã nhận xét [ở đây] (https://stackoverflow.com/questions/858252/alternatives-to-ms-strncpy-s/35193374#35193374) rằng các phiên bản MS không thực sự khớp với các thông số kỹ thuật của Phụ lục K. Vì vậy, nhiều cho tính di động. – riderBill

1

Đối với những người đang sử dụng phiên bản Visual Studio 2017, có vẻ như định nghĩa tiền xử lý cần thiết để chạy các hoạt động không an toàn đã thay đổi. Thay vào đó, hãy sử dụng:

#define _CRT_SECURE_NO_WARNINGS 

Nó sẽ biên dịch sau đó.

3

I'am sử dụng VisualStdio 2008. Trong trường hợp này, tôi thường đặt Preprocessor Definitions

Menu \ Project \ [ProjectName] Properties ... Alt + F7

Nếu nhấp vào menu này hoặc nhấn Alt + F7 trong cửa sổ dự án, bạn có thể xem "Trang thuộc tính" cửa sổ.

Sau đó, xem menu ở bên trái cửa sổ.

Configuration Properties \ C/C++ \ Preprocessor

Sau đó thêm _CRT_SECURE_NO_WARNINGS để \ Preprocessor Định nghĩa.

+0

Hãy xem câu hỏi đầu tiên này [cách trả lời ] (https://stackoverflow.com/help/how-to-answer) Câu hỏi này được trả lời trước, rõ ràng là bạn có thể thêm câu trả lời của mình ở đây Nhưng bạn cần hiểu một số điểm trước khi trả lời. thêm một câu trả lời mà trước đây được thêm vào cùng một mã hoặc gợi ý, thứ hai, đừng thêm câu trả lời quá phức tạp nếu người dùng đã hỏi rất cụ thể về vấn đề và những gì anh ta cần để giải quyết vấn đề này. bạn muốn đề xuất bất cứ điều gì liên quan ng câu trả lời hoặc câu hỏi. –

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