Sdílet prostřednictvím


Upozornění kompilátoru (úroveň 3) C4996

Váš kód používá funkci, člen třídy, proměnnou nebo typedef, která je označená jako zastaralá. Symboly jsou zastaralé pomocí __declspec(deprecated) modifikátoru nebo atributu C++14 [[deprecated]] . Skutečná zpráva upozornění C4996 je určena modifikátorem deprecated nebo atributem deklarace.

Důležité

Toto upozornění je vždy záměrnou zprávou od autora souboru záhlaví, který deklaruje symbol. Nepoužívejte zastaralý symbol, aniž byste porozuměli důsledkům.

Poznámky

Mnoho funkcí, členských funkcí, šablon funkcí a globálních proměnných v knihovnách sady Visual Studio je zastaralých. Některé funkce specifické pro POSIX a Microsoft jsou zastaralé, protože teď mají jiný preferovaný název. Některé funkce knihovny modulu runtime jazyka C jsou zastaralé, protože jsou nezabezpečené a mají bezpečnější variantu. Ostatní jsou zastaralé, protože jsou zastaralé. Zprávy o vyřazení obvykle obsahují navrhované nahrazení zastaralé funkce nebo globální proměnné.

Možnost kompilátoru /sdl (Povolit další kontroly zabezpečení) zvýší toto upozornění na chybu.

Vypnutí upozornění

Pokud chcete vyřešit problém s C4996, obvykle doporučujeme změnit kód. Místo toho použijte navrhované funkce a globální proměnné. Pokud potřebujete použít existující funkce nebo proměnné z důvodů přenositelnosti, můžete upozornění vypnout.

Vypnutí upozornění pro konkrétní řádek kódu

Chcete-li vypnout upozornění pro konkrétní řádek kódu, použijte direktivu warning pragma, #pragma warning(suppress : 4996).

Vypnutí upozornění v souboru

Chcete-li vypnout upozornění v souboru pro vše, co následuje, použijte direktivu pragma upozornění . #pragma warning(disable : 4996)

Vypnutí upozornění v buildech příkazového řádku

Pokud chcete upozornění v sestaveních příkazového řádku globálně vypnout, použijte možnost příkazového /wd4996 řádku.

Vypnutí upozornění pro projekt v sadě Visual Studio

Vypnutí upozornění pro celý projekt v integrovaném vývojovém prostředí sady Visual Studio:

  1. Otevřete dialogové okno Stránky vlastností projektu. Informace o použití dialogového okna Stránky vlastností naleznete v tématu Stránky vlastností.

  2. Vyberte stránku vlastností konfigurace>C/C++>Advanced.

  3. Upravte vlastnost Disable Specific Warnings pro přidání 4996. Pokud chcete změny použít, zvolte OK .

Zakázání upozornění pomocí maker preprocesoru

Makra preprocesoru můžete také použít k vypnutí určitých konkrétních tříd upozornění vyřazení používaných v knihovnách. Tato makra jsou popsaná níže.

Definování makra preprocesoru v sadě Visual Studio:

  1. Otevřete dialogové okno Stránky vlastností projektu. Informace o použití dialogového okna Stránky vlastností naleznete v tématu Stránky vlastností.

  2. Rozbalte preprocesor vlastností > konfigurace C/C++>.

  3. Do vlastnosti Definice preprocesoru přidejte název makra. Zvolte OK , chcete-li projekt uložit, a pak projekt znovu sestavíte.

Chcete-li definovat makro pouze v konkrétních zdrojových souborech, přidejte řádek, například #define EXAMPLE_MACRO_NAME před libovolný řádek, který obsahuje soubor záhlaví.

Tady jsou některé běžné zdroje upozornění a chyb C4996:

Názvy funkcí 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.

Společnost Microsoft přejmenovala některé funkce knihovny SPECIFICKÉ pro POSIX a Microsoft v CRT tak, aby odpovídaly omezením C99 a C++03 u rezervovaných a globálních názvů definovaných implementací. Pouze názvy jsou zastaralé, ne samotné funkce. Ve většině případů se do názvu funkce přidalo úvodní podtržítko, které vytvoří odpovídající název. Kompilátor vydá upozornění na vyřazení původního názvu funkce a navrhne preferovaný název.

Pokud chcete tento problém vyřešit, doporučujeme změnit kód tak, aby místo toho používal navrhované názvy funkcí. Aktualizované názvy jsou ale specifické pro Microsoft. Pokud potřebujete použít existující názvy funkcí z důvodů přenositelnosti, můžete tato upozornění vypnout. Funkce jsou stále dostupné v knihovně pod jejich původními názvy.

Chcete-li vypnout upozornění na vyřazení těchto funkcí, definujte makro _CRT_NONSTDC_NO_WARNINGSpreprocesoru . Toto makro můžete definovat na příkazovém řádku zahrnutím možnosti /D_CRT_NONSTDC_NO_WARNINGS.

Nebezpečné funkce knihovny 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.

Společnost Microsoft zastaralá některé funkce standardní knihovny CRT a C++ a globální funkce, protože jsou k dispozici bezpečnější verze. Většina zastaralých funkcí umožňuje nezaškrtnuté oprávnění ke čtení nebo zápisu do vyrovnávací paměti. Jejich zneužití může vést k vážným problémům se zabezpečením. Kompilátor vydá upozornění na vyřazení těchto funkcí a navrhne upřednostňovanou funkci.

Pokud chcete tento problém vyřešit, doporučujeme místo toho použít funkci nebo proměnnou safe-version . Někdy kvůli přenositelnosti nebo zpětné kompatibilitě nemůžete. Pečlivě ověřte, že v kódu není možné přepsat nebo přečíst vyrovnávací paměť. Pak můžete upozornění vypnout.

Chcete-li vypnout upozornění na vyřazení těchto funkcí v CRT, definujte _CRT_SECURE_NO_WARNINGS.

Chcete-li vypnout upozornění týkající se zastaralých globálních proměnných, definujte _CRT_SECURE_NO_WARNINGS_GLOBALS.

Další informace o těchto zastaralých funkcích a globálních funkcích naleznete v tématu Funkce zabezpečení v CRT a bezpečné knihovny: Standardní knihovna C++.

Nebezpečné standardní funkce knihovny

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

V sadě Visual Studio 2015 se toto upozornění zobrazí v buildech ladění, protože některé šablony funkcí standardní knihovny C++ nekontrolují správnost parametrů. Často je to proto, že pro funkci není k dispozici dostatek informací pro kontrolu hranic kontejneru. Nebo proto, že iterátory mohou být s funkcí nesprávně použity. Toto upozornění vám pomůže identifikovat tyto funkce, protože mohou být zdrojem závažných bezpečnostních otvorů ve vašem programu. Další informace naleznete v tématu Kontrola iterátorů.

Toto upozornění se například zobrazí v režimu ladění, pokud předáte ukazatel std::copyprvku namísto prostého pole. Chcete-li tento problém vyřešit, použijte správně deklarované pole, aby knihovna mohl zkontrolovat rozsahy pole a provést kontrolu hranic.

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

V jazyce C++14 bylo aktualizováno několik standardních algoritmů knihovny, aby měly verze "duálního rozsahu". Pokud používáte verze duálního rozsahu, druhá oblast poskytuje potřebnou kontrolu mezí:

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

Tento příklad ukazuje několik dalších způsobů použití standardní knihovny ke kontrole použití iterátoru a při nezaškrtnutém použití může být nebezpečné:

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

Pokud jste ověřili, že váš kód nemůže mít chybu přetečení vyrovnávací paměti, můžete toto upozornění vypnout. Chcete-li vypnout upozornění pro tyto funkce, definujte _SCL_SECURE_NO_WARNINGS.

Zaškrtnuté iterátory povoleny

K C4996 může dojít také v případě, že nepoužíváte kontrolované iterátor, pokud _ITERATOR_DEBUG_LEVEL je definován jako 1 nebo 2. Pro sestavení v režimu ladění je ve výchozím nastavení nastavená hodnota 2 a pro maloobchodní buildy je nastavená na 0. Další informace naleznete v tématu Kontrola iterátorů.

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

Nebezpečný kód MFC nebo ATL

K C4996 může dojít, pokud používáte funkce MFC nebo ATL, které byly z bezpečnostních důvodů zastaralé.

Pokud chcete tento problém vyřešit, důrazně doporučujeme změnit kód tak, aby místo toho používal aktualizované funkce.

Informace o tom, jak potlačit tato upozornění, naleznete v tématu _AFX_SECURE_NO_WARNINGS.

Zastaralé funkce a proměnné 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.

Některé funkce knihovny a globální proměnné jsou zastaralé. Tyto funkce a proměnné mohou být odebrány v budoucí verzi knihovny. Kompilátor vydá upozornění na vyřazení těchto položek a navrhne upřednostňovanou alternativu.

Pokud chcete tento problém vyřešit, doporučujeme změnit kód tak, aby používal navrženou funkci nebo proměnnou.

Chcete-li vypnout upozornění na vyřazení těchto položek, definujte _CRT_OBSOLETE_NO_WARNINGS. Další informace najdete v dokumentaci k zastaralé funkci nebo proměnné.

Chyby zařazování v kódu CLR

K C4996 může také dojít při použití knihovny zařazování CLR. V tomto případě je C4996 chybou, nikoli upozorněním. K chybě dochází, když použijete marshal_as k převodu mezi dvěma datovými typy, které vyžadují marshal_context třídu. Tato chyba se může zobrazit také v případě, že knihovna zařazování nepodporuje převod. Další informace o zařazování knihovny naleznete v tématu Přehled zařazování v jazyce C++.

Tento příklad vygeneruje C4996, protože zařazování knihovny vyžaduje kontext pro převod z a System::String na .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;
}

Příklad: Zastaralá funkce definovaná uživatelem

Atribut ve vlastním kódu můžete použít deprecated k upozornění volajících, když už některé funkce nedoporučujete používat. V tomto příkladu se C4996 vygeneruje na dvou místech: Jedna pro řádek, na kterém je zastaralá funkce deklarována, a jedna pro řádek, na kterém se funkce používá.

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