Advertencia del compilador (nivel 3) C4996

El código usa una función, un miembro de clase, una variable o una definición de typedef marcadas como en desuso. Los símbolos están en desuso mediante un modificador __declspec(deprecated) o el atributo [[deprecated]] C++14. El modificador deprecated o atributo de la declaración especifica el mensaje de advertencia C4996 real.

Importante

Esta advertencia siempre es un mensaje deliberado del autor del archivo de encabezado que declara el símbolo. No use el símbolo en desuso sin comprender las consecuencias.

Comentarios

Muchas funciones, funciones miembro, plantillas de función y variables globales en las bibliotecas de Visual Studio están en desuso. Algunas, como POSIX y funciones específicas de Microsoft, están en desuso porque ahora tienen un nombre preferido diferente. Algunas funciones de la biblioteca en tiempo de ejecución de C están en desuso porque no son seguras y tienen una variante más segura. Otras están en desuso porque están obsoletas. El mensaje de desuso normalmente incluye un reemplazo sugerido para la función o la variable global en desuso.

La opción del compilador /sdl (Habilitar comprobaciones de seguridad adicionales) eleva esta advertencia a un error.

Desactivar la advertencia

Para corregir un problema de C4996, normalmente se recomienda cambiar el código. En su lugar, use las funciones sugeridas y las variables globales. Si necesita usar las funciones o variables existentes por motivos de portabilidad, puede desactivar la advertencia.

Desactivar la advertencia de una línea de código específica

Para desactivar la advertencia en una línea de código concreta, use pragma warning, #pragma warning(suppress : 4996).

Desactivar la advertencia dentro de un archivo

Para desactivar la advertencia dentro de un archivo para todo lo siguiente, use pragma de advertencia, #pragma warning(disable : 4996).

Desactivar la advertencia en compilaciones de línea de comandos

Para desactivar la advertencia globalmente en compilaciones de línea de comandos, use la opción de línea de comandos /wd4996.

Desactivar la advertencia de un proyecto en Visual Studio

Si desea desactivar la advertencia para un proyecto entero en el IDE de Visual Studio:

  1. Abra el diálogo Páginas de propiedades del proyecto. Para obtener información sobre cómo usar el cuadro de diálogo Páginas de propiedades, consulte Páginas de propiedades.

  2. Seleccione en la página de propiedades Propiedades de configuración>C/C++>Avanzado.

  3. Edite la propiedad Deshabilitar advertencias específicas para agregar 4996. Seleccione Aceptar para aplicar los cambios.

Deshabilitar la advertencia mediante macros de preprocesador

También puede utilizar macros de preprocesador para desactivar determinadas clases de advertencias sobre desuso usadas en las bibliotecas. Estas macros se describen a continuación.

Para definir una macro de preprocesador en Visual Studio:

  1. Abra el diálogo Páginas de propiedades del proyecto. Para obtener información sobre cómo usar el cuadro de diálogo Páginas de propiedades, consulte Páginas de propiedades.

  2. Expanda Propiedades de configuración >C o C++ >Preprocesador.

  3. En la propiedad Definiciones de preprocesador , agregue el nombre de la macro. Seleccione Aceptar para guardar y, luego, vuelva a generar el proyecto.

Para definir una macro solamente en archivos de origen concretos, agregue una línea como #define EXAMPLE_MACRO_NAME antes de cualquier línea que incluya un archivo de encabezado.

Estos son algunos de los orígenes comunes de advertencias y errores de C4996:

Nombres de función 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 cambió el nombre de algunas funciones de biblioteca POSIX y específicas de Microsoft en CRT para cumplir con las restricciones C99 y C++03 en nombres reservados y definidos por la implementación global. Solo los nombres están en desuso, no las funciones en sí. En la mayoría de casos, se agregó un carácter de subrayado inicial al nombre de función para crear un nombre conforme. El compilador emite una advertencia de desuso para los nombres de funciones originales y sugiere el nombre preferido.

Para corregir este problema, normalmente se recomienda cambiar el código para usar los nombres de función sugeridos en su lugar. Sin embargo, los nombres actualizados son específicos de Microsoft. Si necesita usar los nombres de las funciones existentes por motivos de portabilidad, puede desactivar las advertencias. Las funciones siguen estando disponibles en la biblioteca con sus nombres originales.

Para desactivar las advertencias sobre desuso para estas funciones, defina la macro de preprocesador _CRT_NONSTDC_NO_WARNINGS. Puede definir esta macro en la línea de comandos si incluye la opción /D_CRT_NONSTDC_NO_WARNINGS.

Funciones de biblioteca de CRT no seguras

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 desusó algunas funciones y globales de la biblioteca estándar de CRT y C++ porque hay versiones más seguras disponibles. La mayoría de las funciones en desuso permiten el acceso de lectura o escritura no activado a los búferes. Su uso indebido puede dar lugar a problemas graves de seguridad. El compilador emite una advertencia de desuso para estas funciones y sugiere la función preferida.

Para corregir este problema, se recomienda usar la función o variable safe-version en su lugar. A veces no es posibles, por motivos de portabilidad o compatibilidad con versiones anteriores. Compruebe cuidadosamente que no es posible que un búfer sobrescriba o se sobreprocese en el código. A continuación, puede desactivar la advertencia.

Para desactivar las advertencias sobre desuso para estas funciones en CRT, defina _CRT_SECURE_NO_WARNINGS.

Para desactivar las advertencias sobre variables globales en desuso, defina _CRT_SECURE_NO_WARNINGS_GLOBALS.

Para obtener más información sobre estas funciones y globales en desuso, consulte Características de seguridad en CRT y Bibliotecas seguras: estándar de biblioteca C++.

Funciones de biblioteca estándar no 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'

En Visual Studio 2015, esta advertencia aparece en compilaciones de depuración porque determinadas plantillas de función de la biblioteca estándar de C++ no comprueban si hay errores. A menudo, se debe a que no hay suficiente información disponible para la función para comprobar los límites del contenedor. O bien es debido a que los iteradores se pueden usar incorrectamente con la función. Esta advertencia le ayuda a identificar estas funciones, ya que pueden ser una fuente de vulnerabilidades de seguridad en el programa. Para obtener más información, consulte Checked Iterators.

Por ejemplo, esta advertencia aparece en modo de depuración si pasa un puntero de elemento a std::copy, en lugar de una matriz sin formato. Para corregir este problema, use una matriz declarada correctamente, por lo que la biblioteca puede comprobar las extensiones de la matriz y realizar la comprobación de límites.

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

Se actualizaron varios algoritmos de biblioteca estándar para tener versiones de "rango dual" en C++14. Si usa las versiones de intervalo dual, el segundo intervalo proporciona la comprobación de límites necesaria:

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

En este ejemplo se muestran varias maneras más en que se puede usar la biblioteca estándar para comprobar el uso del iterador y cuando el uso no comprobado puede ser peligroso:

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

Si ha comprobado que el código no puede tener un error de saturación del búfer, puede desactivar esta advertencia. Para desactivar las advertencias para estas funciones, defina _SCL_SECURE_NO_WARNINGS.

Iteradores comprobados habilitados

C4996 también puede producirse si no usa un iterador comprobado cuando _ITERATOR_DEBUG_LEVEL se define como 1 o 2. Se establece en 2 de forma predeterminada para las compilaciones del modo de depuración y en 0 para las compilaciones comerciales. Para obtener más información, consulte Checked Iterators.

// 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 o ATL no seguro

C4996 también puede producirse si se utilizan funciones MFC o ATL que quedaron desusadas por razones de seguridad.

Para corregir este problema, se recomienda encarecidamente cambiar el código para usar las funciones actualizadas en su lugar.

Para obtener información sobre cómo suprimir estas advertencias, vea _AFX_SECURE_NO_WARNINGS.

Funciones y variables 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.

Algunas variables globales y funciones de la biblioteca están en desuso por estar obsoletas. Es posible que estas funciones y variables se quiten en una versión futura de la biblioteca. El compilador emite una advertencia de desuso para estos elementos y sugiere la alternativa preferida.

Para corregir este problema, se recomienda cambiar el código para usar la variable o la función sugeridas.

Para desactivar las advertencias sobre desuso para estos elementos, defina _CRT_OBSOLETE_NO_WARNINGS. Para más información, consulte la documentación de la variable o función en desuso.

Cálculo de referencias de errores en código CLR

C4996 también puede producirse cuando se utiliza la biblioteca de cálculo de referencias CLR. En este caso, C4996 es un error y no una advertencia. Este error se producirá al utilizar marshal_as para convertir entre dos tipos de datos que requieren una marshal_contextClase. También recibirá este error cuando la biblioteca de cálculo de referencias no admita una conversión. Para más información sobre la biblioteca de cálculo de referencias, vea Introducción a la serialización en C++.

Este ejemplo genera la advertencia C4996 porque la biblioteca de cálculo de referencias exige un contexto para convertir un objeto System::String 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;
}

Ejemplo: función en desuso definida por el usuario

Puede usar el atributo deprecated en su propio código para advertir a los autores de llamadas cuando ya no se recomienda el uso de determinadas funciones. En este ejemplo, C4996 se genera en dos lugares: uno para la línea en la que se declara la función en desuso y otra para la línea donde se usa la función.

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