Dela via


Kompilatorvarning (nivå 3) C4996

Koden använder en funktion, klassmedlem, variabel eller typedef som har markerats som inaktuell. Symboler är inaktuella med hjälp av en __declspec(deprecated) modifierare eller attributet C++14 [[deprecated]] . Det faktiska C4996-varningsmeddelandet anges av deprecated modifieraren eller attributet för deklarationen.

Viktigt!

Den här varningen är alltid ett avsiktligt meddelande från författaren till huvudfilen som deklarerar symbolen. Använd inte den inaktuella symbolen utan att förstå konsekvenserna.

Anmärkningar

Många funktioner, medlemsfunktioner, funktionsmallar och globala variabler i Visual Studio-bibliotek är inaktuella. Vissa, till exempel POSIX- och Microsoft-specifika funktioner, är inaktuella eftersom de nu har ett annat föredraget namn. Vissa C-körningsbiblioteksfunktioner är inaktuella eftersom de är osäkra och har en säkrare variant. Andra är inaktuella eftersom de är föråldrade. Utfasningsmeddelandena innehåller vanligtvis en föreslagen ersättning för den inaktuella funktionen eller den globala variabeln.

Kompileringsalternativet (Aktivera ytterligare säkerhetskontroller) höjer varningen till ett fel./sdl

Inaktivera varningen

För att åtgärda ett C4996-problem rekommenderar vi vanligtvis att du ändrar koden. Använd de föreslagna funktionerna och globala variablerna i stället. Om du behöver använda befintliga funktioner eller variabler av portabilitetsskäl kan du inaktivera varningen.

Inaktivera varningen för en specifik kodrad

Om du vill inaktivera varningen för en specifik kodrad använder du warning pragma, #pragma warning(suppress : 4996).

Inaktivera varningen i en fil

Om du vill inaktivera varningen i en fil för allt som följer använder du varnings pragma, #pragma warning(disable : 4996).

Inaktivera varningen i kommandoradsversioner

Om du vill inaktivera varningen globalt i kommandoradsversioner använder du /wd4996 kommandoradsalternativet.

Inaktivera varningen för ett projekt i Visual Studio

Så här inaktiverar du varningen för ett helt projekt i Visual Studio IDE:

  1. Öppna dialogrutan Egenskapssidor för projektet. Information om hur du använder dialogrutan Egenskapssidor finns i Egenskapssidor.

  2. Välj egenskapssidan Konfigurationsegenskaper>C/C++>Avancerat .

  3. Redigera egenskapen Inaktivera specifika varningar för att lägga till 4996. Välj OK för att tillämpa ändringarna.

Inaktivera varningen med hjälp av makron för förprocessorn

Du kan också använda makron för förprocessorer för att inaktivera vissa specifika klasser av utfasningsvarningar som används i biblioteken. Dessa makron beskrivs nedan.

Så här definierar du ett makro för processor i Visual Studio:

  1. Öppna dialogrutan Egenskapssidor för projektet. Information om hur du använder dialogrutan Egenskapssidor finns i Egenskapssidor.

  2. Expandera Konfigurationsegenskaper > C/C++ > Förprocessor.

  3. Lägg till makronamnet i egenskapen Förprocessordefinitioner . Välj OK för att spara och återskapa sedan projektet.

Om du bara vill definiera ett makro i specifika källfiler lägger du till en rad, till exempel #define EXAMPLE_MACRO_NAME före en rad som innehåller en rubrikfil.

Här är några av de vanligaste källorna till C4996-varningar och -fel:

POSIX-funktionsnamn

POSIX-namnet för det här objektet är inaktuellt. Använd i stället ISO C- och C++-konforma namn: new-name. Mer information finns i onlinehjälpen.

Microsoft har bytt namn på vissa POSIX- och Microsoft-specifika biblioteksfunktioner i CRT för att överensstämma med C99- och C++03-begränsningar för reserverade och globala implementeringsdefinierade namn. Endast namnen är inaktuella, inte själva funktionerna. I de flesta fall lades ett inledande understreck till i funktionsnamnet för att skapa ett överensstämmande namn. Kompilatorn utfärdar en utfasningsvarning för det ursprungliga funktionsnamnet och föreslår det önskade namnet.

För att åtgärda det här problemet rekommenderar vi vanligtvis att du ändrar koden så att du använder de föreslagna funktionsnamnen i stället. De uppdaterade namnen är dock Microsoft-specifika. Om du behöver använda de befintliga funktionsnamnen av portabilitetsskäl kan du inaktivera dessa varningar. Funktionerna är fortfarande tillgängliga i biblioteket under deras ursprungliga namn.

Om du vill inaktivera utfasningsvarningar för dessa funktioner definierar du makrot _CRT_NONSTDC_NO_WARNINGSpreprocessor . Du kan definiera makrot på kommandoraden genom att inkludera alternativet /D_CRT_NONSTDC_NO_WARNINGS.

Osäkra CRT-biblioteksfunktioner

Den här funktionen eller variabeln kan vara osäker. Överväg att använda safe-version i stället. Om du vill inaktivera utfasning använder du _CRT_SECURE_NO_WARNINGS. Mer information finns i onlinehjälpen.

Microsoft har föråldrat vissa funktioner och globaler för CRT- och C++-standardbibliotek eftersom det finns säkrare versioner tillgängliga. De flesta inaktuella funktioner tillåter omarkerad läs- eller skrivåtkomst till buffertar. Deras missbruk kan leda till allvarliga säkerhetsproblem. Kompilatorn utfärdar en utfasningsvarning för dessa funktioner och föreslår den föredragna funktionen.

För att åtgärda det här problemet rekommenderar vi att du använder funktionen eller variabeln safe-version i stället. Ibland kan du inte, av portabilitets- eller bakåtkompatibilitetsskäl. Kontrollera noggrant att det inte är möjligt att en buffertöverskrivning eller överläsning sker i koden. Sedan kan du inaktivera varningen.

Om du vill inaktivera utfasningsvarningar för dessa funktioner i CRT definierar du _CRT_SECURE_NO_WARNINGS.

Om du vill inaktivera varningar om inaktuella globala variabler definierar du _CRT_SECURE_NO_WARNINGS_GLOBALS.

Mer information om dessa inaktuella funktioner och globaler finns i Säkerhetsfunktioner i CRT och säkra bibliotek: C++ StandardBibliotek.

Osäkra standardbiblioteksfunktioner

'std:: function_name ::_Unchecked_iterators::_Deprecate' Anrop till std:: function_name med parametrar som kan vara osäkra – det här anropet förlitar sig på anroparen för att kontrollera att de anförda värdena är korrekta. Om du vill inaktivera den här varningen använder du -D_SCL_SECURE_NO_WARNINGS. Se dokumentation om hur du använder Visual C++ "Checked Iterators"

I Visual Studio 2015 visas den här varningen i felsökningsversioner eftersom vissa C++ Standard Library-funktionsmallar inte kontrollerar parametrarna för korrekthet. Ofta beror det på att det inte finns tillräckligt med information för funktionen för att kontrollera containergränsen. Eller eftersom iteratorer kan användas felaktigt med funktionen. Den här varningen hjälper dig att identifiera dessa funktioner, eftersom de kan vara en källa till allvarliga säkerhetshål i ditt program. Mer information finns i Kontrollerade iteratorer.

Den här varningen visas till exempel i felsökningsläge om du skickar en elementpekare till std::copyi stället för en vanlig matris. Åtgärda problemet genom att använda en korrekt deklarerad matris, så att biblioteket kan kontrollera matrisens omfattningar och kontrollera gränserna.

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

Flera standardbiblioteksalgoritmer uppdaterades för att ha versioner med "dubbla intervall" i C++14. Om du använder de dubbla intervallversionerna tillhandahåller det andra intervallet nödvändig gränskontroll:

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

Det här exemplet visar flera olika sätt som standardbiblioteket kan användas för att kontrollera iteratoranvändningen och när okontrollerad användning kan vara farlig:

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

Om du har kontrollerat att koden inte kan ha ett buffertöverskridningsfel kan du inaktivera den här varningen. Om du vill inaktivera varningar för dessa funktioner definierar du _SCL_SECURE_NO_WARNINGS.

Kontrollerade iteratorer är aktiverade

C4996 kan också inträffa om du inte använder en markerad iterator när _ITERATOR_DEBUG_LEVEL den definieras som 1 eller 2. Den är inställd på 2 som standard för felsökningslägesversioner och till 0 för detaljhandelsversioner. Mer information finns i Kontrollerade iteratorer.

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

Osäker MFC- eller ATL-kod

C4996 kan inträffa om du använder MFC- eller ATL-funktioner som har föråldrats av säkerhetsskäl.

För att åtgärda det här problemet rekommenderar vi starkt att du ändrar koden så att den använder uppdaterade funktioner i stället.

Information om hur du utelämnar dessa varningar finns i _AFX_SECURE_NO_WARNINGS.

Föråldrade CRT-funktioner och variabler

Den här funktionen eller variabeln har ersatts av nyare biblioteks- eller operativsystemfunktioner. Överväg att använda new_item i stället. Mer information finns i onlinehjälpen.

Vissa biblioteksfunktioner och globala variabler är inaktuella. Dessa funktioner och variabler kan tas bort i en framtida version av biblioteket. Kompilatorn utfärdar en utfasningsvarning för dessa objekt och föreslår det föredragna alternativet.

För att åtgärda det här problemet rekommenderar vi att du ändrar koden så att den föreslagna funktionen eller variabeln används.

Om du vill inaktivera utfasningsvarningar för dessa objekt definierar du _CRT_OBSOLETE_NO_WARNINGS. Mer information finns i dokumentationen för den inaktuella funktionen eller variabeln.

Fel vid marskalkering i CLR-kod

C4996 kan också inträffa när du använder CLR-marskalkningsbiblioteket. I det här fallet är C4996 ett fel, inte en varning. Felet uppstår när du använder marshal_as för att konvertera mellan två datatyper som kräver en marshal_context klass. Du kan också få det här felet när marshaling-biblioteket inte stöder en konvertering. Mer information om marshaling-biblioteket finns i Översikt över marskalkning i C++.

Det här exemplet genererar C4996 eftersom marshaling-biblioteket kräver en kontext för att konvertera från en System::String till en 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;
}

Exempel: Användardefinierad inaktuell funktion

Du kan använda deprecated attributet i din egen kod för att varna anropare när du inte längre rekommenderar användning av vissa funktioner. I det här exemplet genereras C4996 på två platser: En för raden som den inaktuella funktionen deklareras på och en för raden där funktionen används.

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