Avviso del compilatore (livello 3) C4996

Il codice usa una funzione, un membro della classe, una variabile o un typedef contrassegnato come deprecato. I simboli sono deprecati usando un __declspec(deprecated) modificatore o l'attributo C++14 [[deprecated]] . Il messaggio di avviso C4996 effettivo viene specificato dal modificatore o dall'attributo deprecated della dichiarazione.

Importante

Questo avviso è sempre un messaggio intenzionale dell'autore del file di intestazione che dichiara il simbolo. Non usare il simbolo deprecato senza comprendere le conseguenze.

Osservazioni:

Molte funzioni, funzioni membro, modelli di funzione e variabili globali nelle librerie di Visual Studio sono deprecate. Alcune, ad esempio POSIX e funzioni specifiche di Microsoft, sono deprecate perché ora hanno un nome preferito diverso. Alcune funzioni della libreria di runtime C sono deprecate perché non sono sicure e hanno una variante più sicura. Altri sono deprecati perché sono obsoleti. I messaggi di deprecazione in genere includono una sostituzione suggerita per la funzione deprecata o la variabile globale.

L'opzione del /sdl compilatore (Abilita controlli di sicurezza aggiuntivi) eleva questo avviso a un errore.

Disattivare l'avviso

Per risolvere un problema C4996, in genere è consigliabile modificare il codice. Usare invece le funzioni suggerite e le variabili globali. Se è necessario usare le funzioni o le variabili esistenti per motivi di portabilità, è possibile disattivare l'avviso.

Disattivare l'avviso per una riga di codice specifica

Per disattivare l'avviso per una riga di codice specifica, usare il warning pragma , #pragma warning(suppress : 4996).

Disattivare l'avviso all'interno di un file

Per disattivare l'avviso all'interno di un file per tutti gli elementi seguenti, usare il pragma di avviso , #pragma warning(disable : 4996).

Disattivare l'avviso nelle compilazioni della riga di comando

Per disattivare l'avviso a livello globale nelle compilazioni della riga di comando, usare l'opzione della /wd4996 riga di comando.

Disattivare l'avviso per un progetto in Visual Studio

Per disattivare l'avviso per un intero progetto nell'IDE di Visual Studio:

  1. Aprire la finestra di dialogo Pagine delle proprietà per il progetto. Per informazioni su come usare la finestra di dialogo Pagine delle proprietà, vedere Pagine delle proprietà.

  2. Selezionare la pagina delle proprietà Proprietà>di configurazione C/C++>Avanzate.

  3. Modificare la proprietà Disabilita avvisi specifici per aggiungere 4996. Scegliere OK per applicare le modifiche.

Disabilitare l'avviso usando macro del preprocessore

È anche possibile usare macro di preprocessore per disattivare determinate classi specifiche di avvisi di deprecazione usati nelle librerie. Queste macro sono descritte di seguito.

Per definire una macro del preprocessore in Visual Studio:

  1. Aprire la finestra di dialogo Pagine delle proprietà per il progetto. Per informazioni su come usare la finestra di dialogo Pagine delle proprietà, vedere Pagine delle proprietà.

  2. Espandere Proprietà > di configurazione Preprocessore C/C++>.

  3. Nella proprietà Definizioni preprocessore aggiungere il nome della macro. Scegliere OK per salvare e ricompilare il progetto.

Per definire una macro solo in file di origine specifici, aggiungere una riga come #define EXAMPLE_MACRO_NAME prima di qualsiasi riga che includa un file di intestazione.

Ecco alcune delle origini comuni degli avvisi e degli errori C4996:

Nomi di funzione 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.

Microsoft ha rinominato alcune funzioni di libreria specifiche di POSIX e Microsoft in CRT in modo che siano conformi ai vincoli C99 e C++03 sui nomi riservati e globali definiti dall'implementazione. Solo i nomi sono deprecati, non le funzioni stesse. Nella maggior parte dei casi, al nome della funzione è stato aggiunto un carattere di sottolineatura iniziale per creare un nome conforme. Il compilatore genera un avviso di deprecazione per il nome della funzione originale e suggerisce il nome preferito.

Per risolvere questo problema, in genere è consigliabile modificare il codice in modo da usare i nomi di funzione suggeriti. Tuttavia, i nomi aggiornati sono specifici di Microsoft. Se è necessario usare i nomi di funzione esistenti per motivi di portabilità, è possibile disattivare questi avvisi. Le funzioni sono ancora disponibili nella libreria con i nomi originali.

Per disattivare gli avvisi di deprecazione per queste funzioni, definire la macro _CRT_NONSTDC_NO_WARNINGSdel preprocessore . È possibile definire questa macro nella riga di comando includendo l'opzione /D_CRT_NONSTDC_NO_WARNINGS.

Funzioni della libreria CRT unsafe

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 ha deprecato alcune funzioni della libreria standard CRT e C++ e globali perché sono disponibili versioni più sicure. La maggior parte delle funzioni deprecate consente l'accesso in lettura o scrittura non selezionato ai buffer. L'uso improprio può causare gravi problemi di sicurezza. Il compilatore genera un avviso di deprecazione per queste funzioni e suggerisce la funzione preferita.

Per risolvere questo problema, è consigliabile usare invece la funzione o la variabile safe-version . In alcuni casi non è possibile, per motivi di portabilità o compatibilità con le versioni precedenti. Verificare attentamente che non sia possibile che nel codice si verifichi una sovrascrittura o una sovralettura del buffer. È quindi possibile disattivare l'avviso.

Per disattivare gli avvisi di deprecazione per queste funzioni in CRT, definire _CRT_SECURE_NO_WARNINGS.

Per disattivare gli avvisi relativi alle variabili globali deprecate, definire _CRT_SECURE_NO_WARNINGS_GLOBALS.

Per altre informazioni su queste funzioni deprecate e sulle globalità, vedere Funzionalità di sicurezza in CRT e librerie Cassaforte: libreria standard C++.

Funzioni della libreria standard unsafe

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

In Visual Studio 2015 questo avviso viene visualizzato nelle compilazioni di debug perché alcuni modelli di funzioni della libreria standard C++ non controllano la correttezza dei parametri. Spesso è dovuto al fatto che non sono disponibili informazioni sufficienti per la funzione per controllare i limiti del contenitore. In alternativa, poiché gli iteratori possono essere usati in modo non corretto con la funzione . Questo avviso consente di identificare queste funzioni, perché possono essere una fonte di gravi problemi di sicurezza nel programma. Per altre informazioni, vedere Iteratori verificati.

Ad esempio, questo avviso viene visualizzato in modalità debug se si passa un puntatore di elemento a std::copy, invece di una matrice normale. Per risolvere questo problema, usare una matrice dichiarata in modo appropriato, in modo che la libreria possa controllare gli extent della matrice ed eseguire il controllo dei limiti.

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

Diversi algoritmi di libreria standard sono stati aggiornati per avere versioni "dual range" in C++14. Se si usano le versioni a doppio intervallo, il secondo intervallo fornisce il controllo dei limiti necessario:

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

Questo esempio illustra diversi modi in cui la libreria standard può essere usata per controllare l'utilizzo dell'iteratore e quando l'utilizzo non selezionato può essere pericoloso:

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

Se si è verificato che il codice non può avere un errore di overrun del buffer, è possibile disattivare questo avviso. Per disattivare gli avvisi per queste funzioni, definire _SCL_SECURE_NO_WARNINGS.

Iteratori verificati abilitati

C4996 può verificarsi anche se non si usa un iteratore controllato quando _ITERATOR_DEBUG_LEVEL viene definito come 1 o 2. È impostato su 2 per impostazione predefinita per le compilazioni in modalità di debug e su 0 per le build di vendita al dettaglio. Per altre informazioni, vedere Iteratori verificati.

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

Codice MFC o ATL non sicuro

C4996 può verificarsi se si usano funzioni MFC o ATL deprecate per motivi di sicurezza.

Per risolvere questo problema, è consigliabile modificare il codice in modo da usare le funzioni aggiornate.

Per informazioni su come eliminare questi avvisi, vedere _AFX_SECURE_NO_WARNINGS.

Funzioni e variabili CRT obsolete

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

Alcune funzioni e variabili globali della libreria sono deprecate come obsolete. Queste funzioni e variabili potrebbero essere rimosse nelle future versioni della libreria. Il compilatore genera un avviso di deprecazione per questi elementi e suggerisce l'alternativa preferita.

Per risolvere questo problema, è consigliabile modificare il codice in modo da usare la funzione o la variabile suggerita.

Per disattivare gli avvisi di deprecazione per questi elementi, definire _CRT_OBSOLETE_NO_WARNINGS. Per altre informazioni, vedere la documentazione per la funzione o la variabile deprecata.

Marshalling degli errori nel codice CLR

C4996 può verificarsi anche quando si usa la libreria di marshalling CLR. In questo caso, C4996 è un errore, non un avviso. L'errore si verifica quando si usa marshal_as per eseguire la conversione tra due tipi di dati che richiedono una marshal_context classe. È anche possibile ricevere questo errore quando la libreria di marshalling non supporta una conversione. Per altre informazioni sulla libreria di marshalling, vedere Panoramica del marshalling in C++.

Questo esempio genera l'errore C4996 perché la libreria di marshalling richiede un contesto per la conversione da un System::String oggetto a un oggetto 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;
}

Esempio: Funzione deprecata definita dall'utente

È possibile usare l'attributo nel proprio codice per avvisare i chiamanti quando non si consiglia più l'uso deprecated di determinate funzioni. In questo esempio, C4996 viene generato in due posizioni: una per la riga in cui viene dichiarata la funzione deprecata e una per la riga in cui viene usata la funzione.

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