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 modificador __declspec(deprecated)
ou o atributo [[deprecated]]
do C++14. A mensagem de aviso C4996 real é especificada pelo modificador deprecated
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.
Comentários
Muitas funções, funções membro, modelos de função e variáveis globais nas bibliotecas do Visual Studio são preteridas. Alguns, como POSIX e funções específicas da Microsoft, estão preteridos porque agora têm um nome preferencial diferente. Algumas funções de biblioteca de runtime C estão preteridas porque são inseguras e há uma variante mais segura. Outros estão preteridos porque estão obsoletos. As mensagens de preterição geralmente incluem uma substituição sugerida para a função preterida ou variável global.
A opção do compilador /sdl
(Habilitar Verificações de Segurança Adicionais) eleva esse aviso a um erro.
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 pragma warning
, #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:
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.
Selecione a página de propriedades Propriedades de Configuração>C/C++>Avançadas.
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 preterição usados nas bibliotecas. Essas macros estão descritas abaixo.
Para definir uma macro de pré-processador no Visual Studio:
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.
Expanda Propriedades de configuração > C/C++ > Pré-processador.
Na propriedade Definições de pré-processador, adicione o nome da macro. Escolha OK para salvar e 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 C4996:
Nomes de função 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.
A Microsoft renomeou algumas funções de biblioteca específicas POSIX e 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 estão preteridos e não as funções. Na maioria dos casos, um sublinhado à esquerda foi adicionado ao nome da função para criar um nome em conformidade. O compilador emite um aviso de preteriçã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 preterição para essas funções, defina _CRT_NONSTDC_NO_WARNINGS
da macro do 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
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.
A Microsoft preteriu algumas funções e globais da Biblioteca Padrão CRT e C++ porque há versões mais seguras disponíveis. A maioria das funções preteridas permite acesso não verificado de leitura ou gravação aos buffers. Seu uso indevido pode levar a sérios problemas de segurança. O compilador emite um aviso de preteriçã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 isso não é possível por motivos de portabilidade ou compatibilidade com versões anteriores. Verifique cuidadosamente se não é possível que uma substituição ou leitura de buffer ocorra em seu código. Em seguida, você pode desativar o aviso.
Para desativar avisos de preteriçã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 Recursos de segurança nas Bibliotecas CRT e Bibliotecas Seguras: Biblioteca Padrão do C++.
Funções de Biblioteca Padrão não Seguras
'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'
No Visual Studio 2015, esse aviso aparece em compilações de depuração porque certos modelos de função da Biblioteca Padrão C++ não verificam a correção dos parâmetros. Geralmente, é porque não há informações suficientes disponíveis para a função verificar os limites do contêiner. Ou porque 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 falhas de segurança sérias em seu programa. Para obter mais informações, confira 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 não verificado 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 estouro de buffer, você pode desativar esse aviso. Para desativar avisos para essas funções, defina _SCL_SECURE_NO_WARNINGS
.
Iteradores verificados habilitados
O 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 direcionadas ao varejo. Para obter mais informações, confira 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
O C4996 poderá ocorrer se você usar funções MFC ou ATL preteridas por razões de segurança.
Para corrigir esse problema, recomendamos que você altere o 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
This function or variable has been superseded by newer library or operating system functionality. Consider using
new_item
instead. See online help for details.
Algumas funções de biblioteca e variáveis globais estão preteridas por serem obsoletas. Essas funções e variáveis podem ser removidas em uma versão futura da biblioteca. O compilador emite um aviso de preterição para esses itens e sugere a alternativa preferencial.
Para corrigir esse problema, recomendamos que você altere o código para usar a função ou variável sugerida.
Para desativar avisos de preteriçã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
O C4996 também poderá ocorrer quando ao usar a biblioteca de marshaling do CLR. Nesse caso, C4996 é um erro, não um aviso. Esse erro ocorrerá quando você usar marshal_as
para converter entre dois tipos de dados que exigem uma Classe marshal_context
. Você também poderá receber esse erro quando a biblioteca de marshaling não oferecer suporte a uma conversão. Para obter mais informações sobre a biblioteca de marshaling, confira Visão geral de marshaling no C++.
Esse 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 atributo deprecated
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
}