Поделиться через


Предупреждение компилятора (уровень 3) C4996

Код использует функцию, член класса, переменную или типдеф, помеченную как нерекомендуемую. Символы устарели с помощью __declspec(deprecated) модификатора или атрибута C++14 [[deprecated]] . Фактическое предупреждение C4996 указывается модификатором или атрибутом deprecated объявления.

Внимание

Это предупреждение всегда является преднамеренным сообщением автора файла заголовка, объявляющего символ. Не используйте устаревший символ без понимания последствий.

Замечания

Многие функции, функции-члены, шаблоны функций и глобальные переменные в библиотеках Visual Studio устарели. Некоторые функции, такие как POSIX и функции, относящиеся к Корпорации Майкрософт, устарели, так как теперь они имеют другое предпочтительное имя. Некоторые функции библиотеки среды выполнения C устарели, так как они небезопасны и имеют более безопасный вариант. Другие не рекомендуется использовать, так как они устарели. Сообщения об нерекомендуемых сообщениях обычно включают предлагаемую замену устаревшей функции или глобальной переменной.

Параметр /sdl компилятора (включение дополнительных проверок безопасности) повышает этот предупреждение до ошибки.

Отключение предупреждения

Чтобы устранить проблему C4996, обычно рекомендуется изменить код. Вместо этого используйте предлагаемые функции и глобальные переменные. Если вам нужно использовать существующие функции или переменные по причинам переносимости, вы можете отключить предупреждение.

Отключение предупреждения для определенной строки кода

Чтобы отключить предупреждение для определенной строки кода, используйте warning pragma. #pragma warning(suppress : 4996)

Отключение предупреждения в файле

Чтобы отключить предупреждение в файле для всего следующего, используйте предупреждение pragma. #pragma warning(disable : 4996)

Отключение предупреждения в сборках командной строки

Чтобы отключить предупреждение глобально в сборках командной строки, используйте /wd4996 параметр командной строки.

Отключение предупреждения для проекта в Visual Studio

Чтобы отключить предупреждение для всего проекта в интегрированной среде разработки Visual Studio, выполните следующие действия.

  1. Откройте диалоговое окно "Страницы свойств" для проекта. Сведения об использовании диалогового окна "Страницы свойств" см. в разделе "Страницы свойств".

  2. Выберите страницу свойств>конфигурации C/C++>Advanced.

  3. Измените свойство Disable Specific Warnings to add 4996. Нажмите кнопку "ОК ", чтобы применить изменения.

Отключение предупреждения с помощью макросов препроцессора

Вы также можете использовать макросы препроцессора для отключения определенных классов предупреждений о нерекомендуемых предупреждениях, используемых в библиотеках. Эти макросы описаны ниже.

Чтобы определить макрос препроцессора в Visual Studio, выполните следующее:

  1. Откройте диалоговое окно "Страницы свойств" для проекта. Сведения об использовании диалогового окна "Страницы свойств" см. в разделе "Страницы свойств".

  2. Разверните препроцессор свойств > конфигурации C/C++>.

  3. В свойстве "Определения препроцессора" добавьте имя макроса. Нажмите кнопку ОК для сохранения изменений, а затем выполните повторную сборку проекта.

Чтобы определить макрос только в определенных исходных файлах, добавьте строку, например #define EXAMPLE_MACRO_NAME перед любой строкой, включающей файл заголовка.

Ниже приведены некоторые распространенные источники предупреждений и ошибок C4996:

Имена функций 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.

Корпорация Майкрософт переименовывает некоторые функции библиотеки POSIX и Майкрософт в CRT, чтобы соответствовать ограничениям C99 и C++03 для зарезервированных и глобальных имен реализации. Не рекомендуется использовать только имена, а не сами функции. В большинстве случаев в имя функции был добавлен ведущий подчеркивание для создания соответствующего имени. Компилятор выдает предупреждение об отмене имени исходной функции и предлагает предпочтительное имя.

Чтобы устранить эту проблему, обычно рекомендуется изменить код, чтобы вместо этого использовать предлагаемые имена функций. Однако обновленные имена относятся к корпорации Майкрософт. Если вам нужно использовать существующие имена функций по причинам переносимости, вы можете отключить эти предупреждения. Функции по-прежнему доступны в библиотеке под их исходными именами.

Чтобы отключить предупреждения об отключении этих функций, определите макрос _CRT_NONSTDC_NO_WARNINGSпрепроцессора. Этот макрос можно определить в командной строке, включив параметр /D_CRT_NONSTDC_NO_WARNINGS.

Небезопасные функции библиотеки 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.

Корпорация Майкрософт не рекомендует некоторые функции стандартной библиотеки CRT и C++, так как доступны более безопасные версии. Большинство устаревших функций позволяют отменить доступ на чтение или запись к буферам. Их неправильное использование может привести к серьезным проблемам безопасности. Компилятор выдает предупреждение об устаревании для этих функций и предлагает предпочтительную функцию.

Чтобы устранить эту проблему, рекомендуется использовать функцию или переменную safe-version . Иногда вы не можете, по соображениям переносимости или обратной совместимости. Тщательно убедитесь, что в коде невозможно перезаписать или перечитать буфер. Затем вы можете отключить предупреждение.

Чтобы отключить предупреждения об отключении этих функций в CRT, определите _CRT_SECURE_NO_WARNINGS.

Чтобы отключить предупреждения о устаревших глобальных переменных, определите _CRT_SECURE_NO_WARNINGS_GLOBALS.

Дополнительные сведения об этих устаревших функциях и глобальных функциях см. в разделе "Функции безопасности" в CRT и безопасных библиотеках: стандартная библиотека C++.

Небезопасные функции стандартной библиотеки

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

В Visual Studio 2015 это предупреждение отображается в отладочных сборках, так как некоторые шаблоны функций стандартной библиотеки C++ не проверяют правильность параметров. Часто это связано с тем, что для функции недостаточно информации для проверки границ контейнера. Или, так как итераторы могут использоваться неправильно с функцией. Это предупреждение помогает определить эти функции, так как они могут быть источником серьезных отверстий безопасности в программе. Дополнительные сведения см. в разделе "Проверенные итераторы".

Например, это предупреждение отображается в режиме отладки при передаче указателя std::copyэлемента вместо обычного массива. Чтобы устранить эту проблему, используйте соответствующий объявленный массив, чтобы библиотека может проверить экстенты массива и выполнить проверку границ.

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

В C++14 были обновлены несколько стандартных алгоритмов библиотек. При использовании версий двойного диапазона второй диапазон предоставляет необходимую проверку границ:

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

В этом примере показано несколько способов использования стандартной библиотеки для проверки использования итератора, а также при отключении использования может быть опасно:

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

Если вы проверили, что код не может иметь ошибку переполнения буфера, вы можете отключить это предупреждение. Чтобы отключить предупреждения для этих функций, определите _SCL_SECURE_NO_WARNINGS.

Проверенные итераторы включены

C4996 также может возникать, если вы не используете проверенный итератор, если _ITERATOR_DEBUG_LEVEL определен как 1 или 2. По умолчанию для сборок в режиме отладки задано значение 2, а для розничных сборок — 0. Дополнительные сведения см. в разделе "Проверенные итераторы".

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

Небезопасный код MFC или ATL

C4996 может возникать, если вы используете функции MFC или ATL, которые не рекомендуется использовать по соображениям безопасности.

Чтобы устранить эту проблему, настоятельно рекомендуется изменить код для использования обновленных функций.

Сведения о подавлении этих предупреждений см. в разделе _AFX_SECURE_NO_WARNINGS.

Устаревшие функции и переменные CRT

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

Некоторые функции и глобальные переменные библиотеки устарели. Эти функции и переменные могут быть удалены в будущей версии библиотеки. Компилятор выдает предупреждение об устаревании для этих элементов и предлагает предпочтительную альтернативу.

Чтобы устранить эту проблему, рекомендуется изменить код, чтобы использовать предлагаемую функцию или переменную.

Чтобы отключить предупреждения об отключении этих элементов, определите _CRT_OBSOLETE_NO_WARNINGS. Дополнительные сведения см. в документации по устаревшей функции или переменной.

Ошибки маршалинга в коде CLR

C4996 также может возникать при использовании библиотеки маршалинга СРЕДЫ CLR. В этом случае C4996 является ошибкой, а не предупреждением. Ошибка возникает при marshal_as преобразовании между двумя типами данных, для которых требуется marshal_context класс. Эту ошибку также можно получить, если библиотека маршалинга не поддерживает преобразование. Дополнительные сведения о библиотеке маршалинга см. в разделе "Обзор маршалинга" в C++.

В этом примере создается C4996, так как для маршалинговой библиотеки требуется контекст для преобразования из a System::String в .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;
}

Пример: определяемая пользователем нерекомендуемая функция

Атрибут можно использовать deprecated в собственном коде, чтобы предупредить вызывающих пользователей, если вы больше не рекомендуете использовать определенные функции. В этом примере C4996 создается в двух местах: одна для строки, в которой объявлена нерекомендуемая функция, и одна для строки, в которой используется функция.

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