Compartilhar via


Aviso do compilador (nível 3) C4996

Seu código usa uma função, um membro de classe, uma variável ou um typedef marcado como preterido. Os símbolos são preteridos usando um __declspec(deprecated) modificador ou o atributo C++14 [[deprecated]] . A mensagem de aviso C4996 real é especificada pelo deprecated modificador ou atributo da declaração.

Importante

Esse aviso é sempre uma mensagem deliberada do autor do arquivo de cabeçalho que declara o símbolo. Não use o símbolo preterido sem entender as consequências.

Observações

Muitas funções, funções membro, modelos de função e variáveis globais em bibliotecas do Visual Studio são preteridas. Alguns, como POSIX e funções específicas da Microsoft, são preteridos porque agora têm um nome preferencial diferente. Algumas funções de biblioteca de runtime C são preteridas porque são inseguras e têm uma variante mais segura. Outros são preteridos porque estão obsoletos. As mensagens de substituição geralmente incluem uma substituição sugerida para a função preterida ou variável global.

A opção do compilador (Habilitar Verificações de Segurança Adicionais) eleva esse aviso a um erro./sdl

Desativar o aviso

Para corrigir um problema C4996, geralmente recomendamos que você altere seu código. Em vez disso, use as funções sugeridas e as variáveis globais. Se você precisar usar as funções ou variáveis existentes por motivos de portabilidade, poderá desativar o aviso.

Desativar o aviso de uma linha de código específica

Para desativar o aviso de uma linha de código específica, use o warning pragma. #pragma warning(suppress : 4996)

Desativar o aviso em um arquivo

Para desativar o aviso em um arquivo para tudo o que se segue, use o pragma de aviso. #pragma warning(disable : 4996)

Desativar o aviso em builds de linha de comando

Para desativar o aviso globalmente em builds de linha de comando, use a opção /wd4996 de linha de comando.

Desativar o aviso de um projeto no Visual Studio

Para desativar o aviso de um projeto inteiro no IDE do Visual Studio:

  1. Abra a caixa de diálogo Páginas de Propriedades do seu projeto. Para obter informações sobre como usar a caixa de diálogo Páginas de Propriedades, consulte Páginas de Propriedades.

  2. Selecione a página de propriedades> de configuraçãoC/C++>Advanced.

  3. Edite a propriedade Desabilitar Avisos Específicos para adicionar 4996. Escolha OK para aplicar suas alterações.

Desabilitar o aviso usando macros de pré-processador

Você também pode usar macros de pré-processador para desativar determinadas classes específicas de avisos de substituição usados nas bibliotecas. Essas macros são descritas abaixo.

Para definir uma macro de pré-processador no Visual Studio:

  1. Abra a caixa de diálogo Páginas de Propriedades do seu projeto. Para obter informações sobre como usar a caixa de diálogo Páginas de Propriedades, consulte Páginas de Propriedades.

  2. Expanda as propriedades > de configuração do pré-processador C/C++>.

  3. Na propriedade Preprocessor Definitions , adicione o nome da macro. Escolha OK para salvar e, em seguida, recompile seu projeto.

Para definir uma macro somente em arquivos de origem específicos, adicione uma linha como #define EXAMPLE_MACRO_NAME antes de qualquer linha que inclua um arquivo de cabeçalho.

Aqui estão algumas das fontes comuns de avisos e erros do C4996:

Nomes de função POSIX

O nome POSIX para este item foi preterido. Em vez disso, use o nome compatível com ISO C e C++: new-name. Consulte a ajuda online para obter detalhes.

A Microsoft renomeou algumas funções de biblioteca específicas da POSIX e da Microsoft no CRT para estar em conformidade com as restrições C99 e C++03 em nomes reservados e globais definidos pela implementação. Somente os nomes são preteridos, não as próprias funções. Na maioria dos casos, um sublinhado principal foi adicionado ao nome da função para criar um nome em conformidade. O compilador emite um aviso de substituição para o nome da função original e sugere o nome preferencial.

Para corrigir esse problema, geralmente recomendamos que você altere seu código para usar os nomes de função sugeridos. No entanto, os nomes atualizados são específicos da Microsoft. Se você precisar usar os nomes de função existentes por motivos de portabilidade, poderá desativar esses avisos. As funções ainda estão disponíveis na biblioteca em seus nomes originais.

Para desativar avisos de substituição para essas funções, defina a macro _CRT_NONSTDC_NO_WARNINGSdo pré-processador. Você pode definir essa macro na linha de comando incluindo a opção /D_CRT_NONSTDC_NO_WARNINGS.

Funções não seguras da Biblioteca CRT

Essa função ou variável pode não ser segura. Considere usar safe-version em vez disso. Para desabilitar a substituição, use _CRT_SECURE_NO_WARNINGS. Consulte a ajuda online para obter detalhes.

A Microsoft preteriu algumas funções e globais da Biblioteca Padrão do CRT e do C++ porque versões mais seguras estão disponíveis. A maioria das funções preteridas permite acesso de leitura ou gravação desmarcado a buffers. Seu uso indevido pode levar a sérios problemas de segurança. O compilador emite um aviso de substituição para essas funções e sugere a função preferencial.

Para corrigir esse problema, recomendamos que você use a função ou a variável safe-version . Às vezes, não é possível, por motivos de portabilidade ou compatibilidade com versões anteriores. Verifique cuidadosamente se não é possível que um buffer substitua ou seja substituído em seu código. Em seguida, você pode desativar o aviso.

Para desativar avisos de substituição para essas funções no CRT, defina _CRT_SECURE_NO_WARNINGS.

Para desativar avisos sobre variáveis globais preteridas, defina _CRT_SECURE_NO_WARNINGS_GLOBALS.

Para obter mais informações sobre essas funções preteridas e globais, consulte Os Recursos de Segurança nas Bibliotecas CRT e Seguras: Biblioteca Padrão C++.

Funções de Biblioteca Padrão Não Seguras

'std:: function_name ::_Unchecked_iterators::_Deprecate' Chamada para std:: function_name com parâmetros que podem não ser seguros - essa chamada depende do chamador para verificar se os valores passados estão corretos. Para desabilitar esse aviso, use -D_SCL_SECURE_NO_WARNINGS. Consulte a documentação sobre como usar 'Iteradores Verificados' do Visual C++

No Visual Studio 2015, esse aviso aparece em builds de depuração porque determinados modelos de função da Biblioteca Padrão C++ não verificam parâmetros quanto à correção. Geralmente, isso ocorre porque não há informações suficientes disponíveis para a função verificar os limites do contêiner. Ou, como os iteradores podem ser usados incorretamente com a função. Esse aviso ajuda você a identificar essas funções, pois elas podem ser uma fonte de sérias falhas de segurança em seu programa. Para obter mais informações, consulte iteradores verificados.

Por exemplo, esse aviso será exibido no modo de depuração se você passar um ponteiro de elemento para std::copy, em vez de uma matriz simples. Para corrigir esse problema, use uma matriz declarada adequadamente, para que a biblioteca possa verificar as extensões da matriz e fazer a verificação de limites.

// 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ários algoritmos de biblioteca padrão foram atualizados para ter versões de "intervalo duplo" no C++14. Se você usar as versões de intervalo duplo, o segundo intervalo fornecerá a verificação de limites necessária:

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

Este exemplo demonstra várias outras maneiras pelas quais a biblioteca padrão pode ser usada para verificar o uso do iterador e quando o uso desmarcado pode ser perigoso:

// 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 você verificou que seu código não pode ter um erro de sobrecarga de buffer, você pode desativar esse aviso. Para desativar avisos para essas funções, defina _SCL_SECURE_NO_WARNINGS.

Iteradores verificados habilitados

C4996 também poderá ocorrer se você não usar um iterador verificado quando _ITERATOR_DEBUG_LEVEL for definido como 1 ou 2. Ele é definido como 2 por padrão para builds de modo de depuração e 0 para builds de varejo. Para obter mais informações, consulte iteradores verificados.

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

Código MFC ou ATL não seguro

C4996 pode ocorrer se você usar funções MFC ou ATL que foram preteridas por motivos de segurança.

Para corrigir esse problema, recomendamos que você altere seu código para usar funções atualizadas.

Para obter informações sobre como suprimir esses avisos, consulte _AFX_SECURE_NO_WARNINGS.

Funções e variáveis de CRT obsoletas

Essa função ou variável foi substituída por uma biblioteca ou funcionalidade do sistema operacional mais recente. Considere usar new_item em vez disso. Consulte a ajuda online para obter detalhes.

Algumas funções de biblioteca e variáveis globais são preteridas como obsoletas. Essas funções e variáveis podem ser removidas em uma versão futura da biblioteca. O compilador emite um aviso de substituição para esses itens e sugere a alternativa preferida.

Para corrigir esse problema, recomendamos que você altere seu código para usar a função ou variável sugerida.

Para desativar avisos de substituição para esses itens, defina _CRT_OBSOLETE_NO_WARNINGS. Para obter mais informações, consulte a documentação da função ou variável preterida.

Erros de marshaling no código CLR

C4996 também pode ocorrer quando você usa a biblioteca de marshaling clr. Nesse caso, C4996 é um erro, não um aviso. O erro ocorre quando você usa marshal_as para converter entre dois tipos de dados que exigem uma marshal_context Classe. Você também pode receber esse erro quando a biblioteca de marshaling não dá suporte a uma conversão. Para obter mais informações sobre a biblioteca de marshaling, consulte Visão geral do marshaling no C++.

Este exemplo gera C4996 porque a biblioteca de marshaling requer um contexto para converter de um System::String para um 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;
}

Exemplo: função preterida definida pelo usuário

Você pode usar o deprecated atributo em seu próprio código para avisar os chamadores quando você não recomendar mais o uso de determinadas funções. Neste exemplo, C4996 é gerado em dois locais: um para a linha em que a função preterida é declarada e outra para a linha em que a função é usada.

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