Ostrzeżenie kompilatora (poziom 3) C4996

Kod używa funkcji, składowej klasy, zmiennej lub definicji typu, która jest oznaczona jako przestarzała. Symbole są przestarzałe przy użyciu __declspec(deprecated) modyfikatora lub atrybutu C++14 [[deprecated]] . Rzeczywisty komunikat ostrzegawczy C4996 jest określany przez deprecated modyfikator lub atrybut deklaracji.

Ważne

To ostrzeżenie jest zawsze celowym komunikatem od autora pliku nagłówka, który deklaruje symbol. Nie używaj przestarzałego symbolu bez zrozumienia konsekwencji.

Uwagi

Wiele funkcji, funkcji członkowskich, szablonów funkcji i zmiennych globalnych w bibliotekach programu Visual Studio jest przestarzałych. Niektóre funkcje, takie jak POSIX i funkcje specyficzne dla firmy Microsoft, są przestarzałe, ponieważ mają teraz inną preferowaną nazwę. Niektóre funkcje biblioteki środowiska uruchomieniowego języka C są przestarzałe, ponieważ są niezabezpieczone i mają bardziej bezpieczny wariant. Inne są przestarzałe, ponieważ są przestarzałe. Komunikaty o wycofaniu zwykle obejmują sugerowane zastąpienie przestarzałej funkcji lub zmiennej globalnej.

Opcja kompilatora /sdl (Włącz dodatkowe kontrole zabezpieczeń) podnosi to ostrzeżenie do błędu.

Wyłącz ostrzeżenie

Aby rozwiązać problem c4996, zwykle zalecamy zmianę kodu. Zamiast tego użyj sugerowanych funkcji i zmiennych globalnych. Jeśli chcesz użyć istniejących funkcji lub zmiennych ze względów przenośności, możesz wyłączyć ostrzeżenie.

Wyłącz ostrzeżenie dla określonego wiersza kodu

Aby wyłączyć ostrzeżenie dla określonego wiersza kodu, użyj warning pragma, #pragma warning(suppress : 4996).

Wyłączanie ostrzeżenia w pliku

Aby wyłączyć ostrzeżenie w pliku dla wszystkiego, co następuje poniżej, użyj pragma ostrzeżenia, #pragma warning(disable : 4996).

Wyłącz ostrzeżenie w kompilacjach wiersza polecenia

Aby wyłączyć ostrzeżenie globalnie w kompilacjach wiersza polecenia, użyj /wd4996 opcji wiersza polecenia.

Wyłączanie ostrzeżenia dla projektu w programie Visual Studio

Aby wyłączyć ostrzeżenie dotyczące całego projektu w środowisku IDE programu Visual Studio:

  1. Otwórz okno dialogowe Strony właściwości dla projektu. Aby uzyskać informacje na temat korzystania z okna dialogowego Strony właściwości, zobacz Strony właściwości.

  2. Wybierz stronę Właściwości>konfiguracji C/C++>Advanced.

  3. Edytuj właściwość Wyłącz określone ostrzeżenia, aby dodać 4996element . Wybierz przycisk OK , aby zastosować zmiany.

Wyłączanie ostrzeżenia przy użyciu makr preprocesora

Można również użyć makr preprocesora, aby wyłączyć określone klasy ostrzeżeń o wycofaniu używanych w bibliotekach. Te makra zostały opisane poniżej.

Aby zdefiniować makro preprocesora w programie Visual Studio:

  1. Otwórz okno dialogowe Strony właściwości dla projektu. Aby uzyskać informacje na temat korzystania z okna dialogowego Strony właściwości, zobacz Strony właściwości.

  2. Rozwiń węzeł Właściwości > konfiguracji preprocesora C/C++>.

  3. W właściwości Definicje preprocesora dodaj nazwę makra. Wybierz przycisk OK , aby zapisać, a następnie ponownie skompiluj projekt.

Aby zdefiniować makro tylko w określonych plikach źródłowych, dodaj wiersz, taki jak #define EXAMPLE_MACRO_NAME przed dowolnym wierszem zawierającym plik nagłówka.

Oto niektóre typowe źródła ostrzeżeń i błędów C4996:

Nazwy funkcji POSIX

The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: new-name. See online help for details.

Firma Microsoft zmieniła nazwy niektórych funkcji bibliotek poSIX i microsoft w CRT, aby były zgodne z ograniczeniami C99 i C++03 dotyczącymi nazw zarezerwowanych i globalnych zdefiniowanych przez implementację. Tylko nazwy są przestarzałe, a nie same funkcje. W większości przypadków do nazwy funkcji dodano wiodący znak podkreślenia, aby utworzyć zgodną nazwę. Kompilator wystawia ostrzeżenie o wycofaniu oryginalnej nazwy funkcji i sugeruje preferowaną nazwę.

Aby rozwiązać ten problem, zwykle zalecamy zmianę kodu tak, aby zamiast tego używał sugerowanych nazw funkcji. Jednak zaktualizowane nazwy są specyficzne dla firmy Microsoft. Jeśli chcesz użyć istniejących nazw funkcji ze względów przenośności, możesz wyłączyć te ostrzeżenia. Funkcje są nadal dostępne w bibliotece pod ich oryginalnymi nazwami.

Aby wyłączyć ostrzeżenia o wycofaniu dla tych funkcji, zdefiniuj makro _CRT_NONSTDC_NO_WARNINGSpreprocesora . To makro można zdefiniować w wierszu polecenia, włączając opcję /D_CRT_NONSTDC_NO_WARNINGS.

Niebezpieczne funkcje biblioteki CRT

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.

Firma Microsoft wycofała niektóre funkcje biblioteki standardowej I CRT i C++, ponieważ są dostępne bardziej bezpieczne wersje. Większość przestarzałych funkcji umożliwia niezaznaczony dostęp do odczytu lub zapisu do buforów. Ich niewłaściwe użycie może prowadzić do poważnych problemów z zabezpieczeniami. Kompilator wystawia ostrzeżenie o wycofaniu tych funkcji i sugeruje preferowaną funkcję.

Aby rozwiązać ten problem, zalecamy użycie funkcji lub zmiennej safe-version . Czasami nie można, ze względu na przenośność lub zgodność z poprzednimi wersjami. Dokładnie sprawdź, czy nie można zastąpić buforu ani przeczytać go w kodzie. Następnie możesz wyłączyć ostrzeżenie.

Aby wyłączyć ostrzeżenia o wycofaniu dla tych funkcji w narzędziu CRT, zdefiniuj wartość _CRT_SECURE_NO_WARNINGS.

Aby wyłączyć ostrzeżenia dotyczące przestarzałych zmiennych globalnych, zdefiniuj _CRT_SECURE_NO_WARNINGS_GLOBALS.

Aby uzyskać więcej informacji na temat tych przestarzałych funkcji i globalnych, zobacz Funkcje zabezpieczeń w bibliotece CRT i Sejf: Standardowa biblioteka C++.

Niebezpieczne funkcje standardowej biblioteki

'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'

W programie Visual Studio 2015 to ostrzeżenie jest wyświetlane w kompilacjach debugowania, ponieważ niektóre szablony funkcji biblioteki standardowej języka C++ nie sprawdzają parametrów pod kątem poprawności. Często jest to spowodowane tym, że za mało informacji jest dostępnych dla funkcji w celu sprawdzenia granic kontenera. Lub, ponieważ iteratory mogą być niepoprawnie używane z funkcją. To ostrzeżenie pomaga zidentyfikować te funkcje, ponieważ mogą być źródłem poważnych luk w zabezpieczeniach w programie. Aby uzyskać więcej informacji, zobacz Sprawdzono iteratory.

Na przykład to ostrzeżenie jest wyświetlane w trybie debugowania, jeśli przekazujesz wskaźnik elementu do std::copy, a nie w postaci zwykłej tablicy. Aby rozwiązać ten problem, użyj odpowiednio zadeklarowanej tablicy, aby biblioteka mogła sprawdzać zakresy tablicy i sprawdzać ograniczenia.

// 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
}

Zaktualizowano kilka standardowych algorytmów biblioteki, aby mieć wersje "podwójny zakres" w języku C++14. Jeśli używasz wersji z dwoma zakresami, drugi zakres zapewnia niezbędne sprawdzanie granic:

// 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;
}

W tym przykładzie pokazano kilka sposobów, w jaki biblioteka standardowa może służyć do sprawdzania użycia iteratora, a w przypadku niezaznaczonego użycia może być niebezpieczne:

// 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);
}

Jeśli sprawdzono, że kod nie może mieć błędu przepełniania buforu, możesz wyłączyć to ostrzeżenie. Aby wyłączyć ostrzeżenia dotyczące tych funkcji, zdefiniuj wartość _SCL_SECURE_NO_WARNINGS.

Zaznaczone iteratory włączone

C4996 może również wystąpić, jeśli nie używasz zaznaczonego iteratora, gdy _ITERATOR_DEBUG_LEVEL jest zdefiniowany jako 1 lub 2. Dla kompilacji trybu debugowania jest domyślnie ustawiona wartość 2, a dla kompilacji detalicznych jest ustawiona wartość 0. Aby uzyskać więcej informacji, zobacz Sprawdzono iteratory.

// 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
}

Niebezpieczny kod MFC lub ATL

C4996 może wystąpić, jeśli używasz funkcji MFC lub ATL, które były przestarzałe ze względów bezpieczeństwa.

Aby rozwiązać ten problem, zdecydowanie zalecamy zmianę kodu w celu używania zaktualizowanych funkcji.

Aby uzyskać informacje na temat pomijania tych ostrzeżeń, zobacz _AFX_SECURE_NO_WARNINGS.

Przestarzałe funkcje i zmienne CRT

This function or variable has been superseded by newer library or operating system functionality. Consider using new_item instead. See online help for details.

Niektóre funkcje biblioteki i zmienne globalne są przestarzałe. Te funkcje i zmienne mogą zostać usunięte w przyszłej wersji biblioteki. Kompilator wystawia ostrzeżenie o wycofaniu tych elementów i sugeruje preferowaną alternatywę.

Aby rozwiązać ten problem, zalecamy zmianę kodu tak, aby korzystał z sugerowanej funkcji lub zmiennej.

Aby wyłączyć ostrzeżenia o wycofaniu dla tych elementów, zdefiniuj element _CRT_OBSOLETE_NO_WARNINGS. Aby uzyskać więcej informacji, zobacz dokumentację przestarzałej funkcji lub zmiennej.

Przeprowadzanie marshalingu błędów w kodzie CLR

C4996 może również wystąpić podczas korzystania z biblioteki marshalingu CLR. W tym przypadku C4996 jest błędem, a nie ostrzeżeniem. Błąd występuje podczas konwertowania marshal_as między dwoma typami danych, które wymagają marshal_context klasy. Ten błąd można również otrzymać, gdy biblioteka marshalingowa nie obsługuje konwersji. Aby uzyskać więcej informacji na temat biblioteki marshalingowej, zobacz Omówienie marshalingu w języku C++.

W tym przykładzie jest generowany kod C4996, ponieważ biblioteka marshalingowa wymaga kontekstu do konwersji z elementu na System::String .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;
}

Przykład: przestarzała funkcja zdefiniowana przez użytkownika

Możesz użyć atrybutu deprecated we własnym kodzie, aby ostrzegać osoby wywołujące, gdy nie zaleca się już używania określonych funkcji. W tym przykładzie C4996 jest generowany w dwóch miejscach: jeden dla wiersza, w którym jest zadeklarowana przestarzała funkcja, i jeden dla wiersza, w którym jest używana funkcja.

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

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

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

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