編譯器警告 (層級 3) C4996Compiler Warning (level 3) C4996

編譯器遇到已被取代的宣告。The compiler encountered a deprecated declaration. 這項警告一律是審慎的文件庫或包含的標頭檔,您不應該使用已被取代的符號而不需要瞭解後果,否則作者提供的訊息。This warning is always a deliberate message from the author of the library or included header file that you should not use the deprecated symbol without understanding the consequences. 實際的警告訊息是已被取代的修飾詞或屬性宣告中的站台所指定。The actual warning message is specified by the deprecation modifier or attribute at the site of the declaration.

這些是一些常見的 C4996 訊息,產生的 C 執行階段程式庫和標準程式庫,但不是詳盡的清單。These are some common C4996 messages generated by the C Runtime Library and the Standard Library, but not an exhaustive list. 遵循下列連結,或閱讀的方式來修正此問題,或關閉的警告。Follow the links or read on for ways to fix the issue or to turn the warning off.

原因Cause

當編譯器遇到函式或變數標示為,就會發生 C4996過時利用__declspec(deprecated)修飾詞,或當您嘗試存取函式、 類別成員或具有 C + + 14 的 typedef [[過時]] 屬性。C4996 occurs when the compiler encounters a function or variable that is marked as deprecated by using a __declspec(deprecated) modifier, or when you attempt to access a function, class member or typedef that has the C++14 [[deprecated]] attribute. 您可以使用__declspec(deprecated)修飾詞或[[deprecated]]屬性自行在您的程式庫或標頭檔,以警告您有關已被取代的函式、 變數、 成員或 typedef 的用戶端。You can use the __declspec(deprecated) modifier or [[deprecated]] attribute yourself in your libraries or header files to warn your clients about deprecated functions, variables, members, or typedefs.

備註Remarks

許多函式、 成員函式、 樣板函式和在 Visual Studio 中的程式庫中的全域變數會標示已被取代Many functions, member functions, template functions, and global variables in the libraries in Visual Studio are marked as deprecated. 這些函式會被取代,因為它們可能會有不同的慣用的名稱、 可能不安全或有更安全的變體,或可能已經過時。These functions are deprecated because they may have a different preferred name, may be insecure or have a more secure variant, or may be obsolete. 許多已被取代的訊息,包括建議的取代已被取代的函式或全域變數。Many deprecation messages include a suggested replacement for the deprecated function or global variable.

若要修正此問題,我們通常建議您變更程式碼以改用建議的更安全的或更新函式和全域變數。To fix this issue, we usually recommend you change your code to use the suggested safer or updated functions and global variables instead. 如果您需要使用現有的函式或變數,可攜性的原因,警告可以關閉。If you need to use the existing functions or variables for portability reasons, the warning can be turned off.

將警告關閉,而不需要修正問題To turn the warning off without fixing the issue

您可以藉由關閉特定一行程式碼的警告警告pragma, #pragma warning(suppress : 4996)You can turn off the warning for a specific line of code by using the warning pragma, #pragma warning(suppress : 4996). 您也可以關閉警告檔案內使用警告 pragma, #pragma warning(disable : 4996)You can also turn the warning off within a file by using the warning pragma, #pragma warning(disable : 4996).

您可以關閉警告全域命令列組建中使用 /wd4996命令列選項。You can turn the warning off globally in command line builds by using the /wd4996 command line option.

若要關閉 Visual Studio IDE 中的整個專案的警告:To turn off the warning for an entire project in the Visual Studio IDE:

  • 開啟屬性頁為您的專案 對話方塊。Open the Property Pages dialog for your project. 如需如何使用 [屬性頁] 對話方塊的資訊,請參閱屬性頁For information on how to use the Property Pages dialog, see Property Pages.
  • 選取 組態屬性C /C++進階頁面。Select the Configuration Properties, C/C++, Advanced page.
  • 編輯停用特定警告屬性,即可加入4996Edit the Disable Specific Warnings property to add 4996. 選擇確定以套用變更。Choose OK to apply your changes.

您也可以使用前置處理器巨集關閉某些特定的類別之程式庫中使用的取代警告。You can also use preprocessor macros to turn off certain specific classes of deprecation warnings used in the libraries. 以下將說明這些巨集。These macros are described below.

若要在 Visual Studio 中定義前置處理器巨集:To define a preprocessor macro in Visual Studio:

  • 開啟屬性頁為您的專案 對話方塊。Open the Property Pages dialog for your project. 如需如何使用 [屬性頁] 對話方塊的資訊,請參閱屬性頁For information on how to use the Property Pages dialog, see Property Pages.
  • 依序展開組態屬性 > C /C++ > 前置處理器Expand Configuration Properties > C/C++ > Preprocessor.
  • 前置處理器定義屬性新增巨集名稱。In the Preprocessor Definitions property, add the macro name. 選擇 [確定] 加以儲存,然後重建您的專案。Choose OK to save, and then rebuild your project.

若要定義巨集只能在特定的原始程式檔中,加入一行例如#define EXAMPLE_MACRO_NAME之前任一行,其中包含的標頭檔。To define a macro only in specific source files, add a line such as #define EXAMPLE_MACRO_NAME before any line that includes a header file.

C4996 的特定訊息Specific C4996 messages

以下是一些常見的 C4996 警告和錯誤的來源。Here are some of the common sources of C4996 warnings and errors.

POSIX 函式名稱POSIX function names

此項目的 POSIX 名稱已被取代。相反地,使用 ISO C 與C++標準的名稱: new_nameThe POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: new_name. 請參閱線上說明,如需詳細資訊。See online help for details.

Microsoft 已重新命名以依照 C99 與 c++03 規則實作所定義的全域函式名稱的 CRT 中的某些 POSIX 函式。Microsoft has renamed some POSIX functions in the CRT to conform with C99 and C++03 rules for implementation-defined global function names. 只有原始 POSIX 名稱已被取代,函式本身。Only the original POSIX names are deprecated, not the functions themselves. 在大多數情況下,POSIX 函式名稱前會加上底線來表示符合標準的名稱。In most cases, a leading underscore was added to the POSIX function name to create a standard conformant name. 編譯器會發出取代警告,原始的函式名稱,並建議慣用的名稱。The compiler issues a deprecation warning for the original function name, and suggests the preferred name.

若要修正此問題,我們通常建議您變更程式碼以改用建議的函式名稱。To fix this issue, we usually recommend you change your code to use the suggested function names instead. 不過,更新的名稱是 Microsoft 特定的。However, the updated names are Microsoft-specific. 如果您需要使用現有的函式名稱的可攜性的理由,您可以關閉這些警告。If you need to use the existing function names for portability reasons, you can turn these warnings off. POSIX 函式仍在原來的名稱下的文件庫中。The POSIX functions are still available in the library under their original names.

若要關閉這些函式已被取代警告,請定義前置處理器巨集 _CRT_NONSTDC_無_警告To turn off deprecation warnings for these functions, define the preprocessor macro _CRT_NONSTDC_NO_WARNINGS. 您可以定義此巨集,在命令列加上選項/D_CRT_NONSTDC_NO_WARNINGSYou can define this macro at the command line by including the option /D_CRT_NONSTDC_NO_WARNINGS.

不安全的 CRT 程式庫函式Unsafe CRT Library functions

此函式或變數可能不安全。請考慮使用 safe_version 改。若要停用已被取代,請使用_CRT_SECURE_NO_警告。如需詳細資料,請參閱線上說明。This function or variable may be unsafe. Consider using safe_version instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

Microsoft 已取代某些 CRT 與C++標準程式庫函式和全域變數,以更安全的版本。Microsoft has deprecated some CRT and C++ Standard Library functions and globals in favor of more secure versions. 在大部分情況下,取消核取的讀取或寫入存取權可能會導致嚴重的安全性問題的緩衝區,可讓已被取代的函式。In most cases, the deprecated functions allow unchecked read or write access to buffers, which can lead to serious security issues. 編譯器會為這些函式發出已被取代的警告,並建議所應使用的函式。The compiler issues a deprecation warning for these functions, and suggests the preferred function.

若要修正此問題,我們建議您使用函式或變數safe_version改。To fix this issue, we recommend you use the function or variable safe_version instead. 如果您已經確認它並不適用緩衝區覆寫,或 overread 出現在您的程式碼,而且您無法變更的程式碼可攜性的理由,您可以關閉此警告。If you have verified that it's not possible for a buffer overwrite or overread to occur in your code, and you cannot change the code for portability reasons, you can turn off the warning.

若要關閉 CRT 中這些函式已被取代警告,請定義 _CRT_SECURE_無_警告To turn off deprecation warnings for these functions in the CRT, define _CRT_SECURE_NO_WARNINGS. 若要關閉已被取代的全域變數的相關警告,請定義 _CRT_SECURE_無_警告_GLOBALSTo turn off warnings about deprecated global variables, define _CRT_SECURE_NO_WARNINGS_GLOBALS. 如需有關這些已被取代的函式和全域變數的詳細資訊,請參閱 < CRT 中的安全性功能安全程式庫:C++標準程式庫For more information about these deprecated functions and globals, see Security Features in the CRT and Safe Libraries: C++ Standard Library.

不安全的標準程式庫函式Unsafe Standard Library functions

' std::function_name::_未核取_迭代器::_Deprecate' 呼叫 std::function_name 使用參數的可能不安全-此呼叫須由呼叫端檢查通過的值是否正確。若要停用這個警告,請使用 -D_SCL_SECURE_NO_警告。如何使用視覺效果,請參閱文件C++' Checked Iterators''std::function_name::_Unchecked_iterators::_Deprecate' Call to std::function_name with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'

這個警告會出現在偵錯組建因為某些C++標準程式庫範本函式不會檢查參數的正確性。This warning appears in debug builds because certain C++ Standard Library template functions do not check parameters for correctness. 在大部分情況下,這是因為沒有足夠的資訊可供函式,以檢查容器範圍中,或可能不正確地使用迭代器,與函式。In most cases, this is because not enough information is available to the function to check container bounds, or because iterators may be used incorrectly with the function. 這項警告有助於您識別這些函式會使用,因為它們可能是嚴重的安全性漏洞,在程式中的來源。This warning helps you identify these function uses, because they may be a source of serious security holes in your program. 如需詳細資訊,請參閱 Checked IteratorsFor more information, see Checked Iterators.

比方說,這個警告會出現在偵錯模式如果您傳遞的項目指標std::copy而不是純文字的陣列。For example, this warning appears in Debug mode if you pass an element pointer to std::copy instead of a plain array. 若要修正此問題,請使用適當宣告的陣列,讓程式庫可以檢查陣列範圍,並執行界限檢查。To fix this issue, use an appropriately declared array, so the library can check the array extents and do bounds checking.

// C4996_copyarray.cpp
// compile with: cl /c /W4 /D_DEBUG C4996_copyarray.cpp
#include <algorithm>

void example(char const * const src) {
    char dest[1234];
    char * pdest3 = dest + 3;
    std::copy(src, src + 42, pdest3); // C4996
    std::copy(src, src + 42, dest);   // OK, copy can tell that dest is 1234 elements
}

數個標準程式庫演算法已更新為 C + + 14 中有 「 雙重範圍 」 版本。Several standard library algorithms were updated to have "dual range" versions in C++14. 如果您使用雙重範圍版本時,第二個範圍會提供必要的繫結檢查:If you use the dual range versions, the second range provides the necessary bounds checking:

// C4996_containers.cpp
// compile with: cl /c /W4 /D_DEBUG C4996_containers.cpp
#include <algorithm>

bool example(
    char const * const left,
    const size_t leftSize,
    char const * const right,
    const size_t rightSize)
{
    bool result = false;
    result = std::equal(left, left + leftSize, right); // C4996
    // To fix, try this form instead:
    // result = std::equal(left, left + leftSize, right, right + rightSize); // OK
    return result;
}

此範例示範數個標準程式庫可用來檢查迭代器使用方式的更多方式,當未核取的使用方式可能會造成危險:This example demonstrates several more ways the standard library may be used to check iterator usage, and when unchecked usage may be dangerous:

// C4996_standard.cpp
// compile with: cl /EHsc /W4 /MDd C4996_standard.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <numeric>
#include <string>
#include <vector>

using namespace std;

template <typename C> void print(const string& s, const C& c) {
    cout << s;

    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

int main()
{
    vector<int> v(16);
    iota(v.begin(), v.end(), 0);
    print("v: ", v);

    // OK: vector::iterator is checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    vector<int> v2(16);
    transform(v.begin(), v.end(), v2.begin(), [](int n) { return n * 2; });
    print("v2: ", v2);

    // OK: back_insert_iterator is marked as checked in debug mode
    // (i.e. an overrun is impossible)
    vector<int> v3;
    transform(v.begin(), v.end(), back_inserter(v3), [](int n) { return n * 3; });
    print("v3: ", v3);

    // OK: array::iterator is checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    array<int, 16> a4;
    transform(v.begin(), v.end(), a4.begin(), [](int n) { return n * 4; });
    print("a4: ", a4);

    // OK: Raw arrays are checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    // NOTE: This applies only when raw arrays are
    // given to C++ Standard Library algorithms!
    int a5[16];
    transform(v.begin(), v.end(), a5, [](int n) { return n * 5; });
    print("a5: ", a5);

    // WARNING C4996: Pointers cannot be checked in debug mode
    // (i.e. an overrun triggers undefined behavior)
    int a6[16];
    int * p6 = a6;
    transform(v.begin(), v.end(), p6, [](int n) { return n * 6; });
    print("a6: ", a6);

    // OK: stdext::checked_array_iterator is checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    int a7[16];
    int * p7 = a7;
    transform(v.begin(), v.end(),
        stdext::make_checked_array_iterator(p7, 16),
        [](int n) { return n * 7; });
    print("a7: ", a7);

    // WARNING SILENCED: stdext::unchecked_array_iterator
    // is marked as checked in debug mode, but it performs no checking,
    // so an overrun triggers undefined behavior
    int a8[16];
    int * p8 = a8;
    transform( v.begin(), v.end(),
        stdext::make_unchecked_array_iterator(p8),
        [](int n) { return n * 8; });
    print("a8: ", a8);
}

如果您已經確認您的程式碼不能有緩衝區滿溢會觸發這個警告的標準程式庫函式中的錯誤,您可能想要關閉此警告。If you have verified that your code cannot have a buffer overrun error in the Standard Library functions that trigger this warning, you may want to turn this warning off. 若要關閉這些函式的警告,請定義 _SCL_SECURE_無_警告To turn off warnings for these functions, define _SCL_SECURE_NO_WARNINGS.

啟用已檢查的迭代器Checked iterators enabled

如果您不要使用已檢查的迭代器,進行編譯時,也會發生 C4996_ITERATOR_DEBUG_LEVEL定義為 1 或 2。C4996 can also occur if you do not use a checked iterator when compiling with _ITERATOR_DEBUG_LEVEL defined as 1 or 2. 它會設定為 2,根據預設,偵錯模式組建,並為零售組建的 0。It is set to 2 by default for debug mode builds, and to 0 for retail builds. 如需詳細資訊,請參閱 Checked IteratorsSee Checked Iterators for more information.

// C4996_checked.cpp
// compile with: /EHsc /W4 /MDd C4996_checked.cpp
#define _ITERATOR_DEBUG_LEVEL 2

#include <algorithm>
#include <iterator>

using namespace std;
using namespace stdext;

int main() {
    int a[] = { 1, 2, 3 };
    int b[] = { 10, 11, 12 };
    copy(a, a + 3, b + 1);   // C4996
    // try the following line instead:
    // copy(a, a + 3, checked_array_iterator<int *>(b, 3));   // OK
}

不安全的 MFC 或 ATL 程式碼Unsafe MFC or ATL code

如果您使用 MFC 或 ATL 函式已被取代,基於安全性理由,也可能會發生 C4996。C4996 can also occur if you use MFC or ATL functions that were deprecated for security reasons.

若要修正此問題,我們強烈建議您變更您的程式碼,改為使用更新的函式。To fix this issue, we strongly recommend you change your code to use updated functions instead.

如需如何隱藏這些警告的詳細資訊,請參閱_AFX_SECURE_NO_WARNINGSFor information on how to suppress these warnings, see _AFX_SECURE_NO_WARNINGS.

已淘汰的 CRT 函式和變數Obsolete CRT functions and variables

此函式或變數已被較新的文件庫或作業系統功能取代。請考慮使用 new_item 改。如需詳細資料,請參閱線上說明。This function or variable has been superseded by newer library or operating system functionality. Consider using new_item instead. See online help for details.

某些程式庫函式與全域變數因為過時而被取代。Some library functions and global variables are deprecated as obsolete. 這些函式及變數可能會從後續版本的程式庫中移除。These functions and variables may be removed in a future version of the library. 編譯器會為這些函式發出已被取代的警告,並建議所應使用的函式。The compiler issues a deprecation warning for these items, and suggests the preferred alternative.

若要修正此問題,我們建議您變更程式碼以使用建議的函式或變數。To fix this issue, we recommend you change your code to use the suggested function or variable.

若要關閉這些項目已被取代警告,請定義 _CRT_過時_無_警告To turn off deprecation warnings for these items, define _CRT_OBSOLETE_NO_WARNINGS. 如需詳細資訊,請參閱文件中所列之已被取代的函式或變數。For more information, see the documentation for the deprecated function or variable.

CLR 程式碼中的封送處理錯誤Marshalling errors in CLR code

當您使用 CLR 封送處理程式庫時,也可能會發生 C4996。C4996 can also occur when you use the CLR marshaling library. 在此情況下,C4996 是錯誤而非警告。In this case C4996 is an error, not a warning. 當您使用時,就會發生此錯誤marshal_as需要兩個資料類型之間轉換marshal_context 類別This error occurs when you use marshal_as to convert between two data types that require a marshal_context Class. 封送處理程式庫不支援轉換時,您也可以收到此錯誤。You can also receive this error when the marshaling library does not support a conversion. 如需封送處理程式庫的詳細資訊,請參閱 Overview of Marshaling in C++For more information about the marshaling library, see Overview of Marshaling in C++.

因為封送處理程式庫需要內容,才能從轉換這個範例會產生 C4996System::Stringconst char *This example generates C4996 because the marshaling library requires a context to convert from a System::String to a const char *.

// C4996_Marshal.cpp
// compile with: /clr
// C4996 expected
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>

using namespace System;
using namespace msclr::interop;

int main() {
   String^ message = gcnew String("Test String to Marshal");
   const char* result;
   result = marshal_as<const char*>( message );
   return 0;
}

範例:使用者已被取代的函式Example: User-defined deprecated function

警告的呼叫端,當您不再建議使用的特定函式時,您可以在自己的程式碼中使用已被取代的屬性。You can use the deprecated attribute in your own code to warn callers when you no longer recommend use of certain functions. 在此範例中,使用函數的程式行及列上已被取代的函式宣告,會產生 C4996。In this example, C4996 is generated for the line on which the deprecated function is declared, and for the line on which the function is used.

// C4996.cpp
// compile with: /W3
// C4996 warning expected
#include <stdio.h>

// #pragma warning(disable : 4996)
void func1(void) {
   printf_s("\nIn func1");
}

__declspec(deprecated) void func1(int) {
   printf_s("\nIn func2");
}

int main() {
   func1();
   func1(1);    // C4996
}