次の方法で共有


コンパイラの警告 (レベル 3) C4996

コードでは、 非推奨とマークされている関数、クラス メンバー、変数、または typedef を使用します。 シンボルは、 __declspec(deprecated) 修飾子または C++14 [[deprecated]] 属性を使用して非推奨とされます。 実際の C4996 警告メッセージは、宣言の deprecated 修飾子または属性によって指定されます。

Important

この警告は、シンボルを宣言するヘッダー ファイルの作成者からの意図的なメッセージです。 結果を理解せずに、非推奨のシンボルを使用しないでください。

注釈

Visual Studio ライブラリの多くの関数、メンバー関数、関数テンプレート、およびグローバル変数は 非推奨です。 POSIX や Microsoft 固有の関数など、一部の関数は、別の優先名を持つようになったため、非推奨とされます。 一部の C ランタイム ライブラリ関数は安全でないため、非推奨とされ、より安全なバリアントがあります。 他のユーザーは廃止されているため、非推奨です。 非推奨のメッセージには、通常、非推奨の関数またはグローバル変数の置換候補が含まれます。

/sdl (追加のセキュリティ チェックを有効にする) コンパイラ オプションは、この警告をエラーに昇格させます。

警告をオフにする

C4996 の問題を解決するには、通常、コードを変更することをお勧めします。 代わりに、推奨される関数とグローバル変数を使用してください。 移植性の理由から既存の関数または変数を使用する必要がある場合は、警告をオフにすることができます。

特定のコード行の警告をオフにする

特定のコード行に対する警告をオフにするには、 warning プラグマ ( #pragma warning(suppress : 4996)) を使用します。

ファイル内の警告をオフにする

その後のすべてのファイル内の警告をオフにするには、警告プラグマ ( #pragma warning(disable : 4996)) を使用します。

コマンド ライン ビルドで警告をオフにする

コマンド ライン ビルドで警告をグローバルにオフにするには、 /wd4996 コマンド ライン オプションを使用します。

Visual Studio でプロジェクトの警告をオフにする

Visual Studio IDE でプロジェクト全体の警告をオフにするには、次のようにします:

  1. プロジェクトの [プロパティ ページ] ダイアログを開きます。 [プロパティ ページ] ダイアログの使用方法の詳細については、プロパティ ページを参照してください。

  2. 構成プロパティ>C/C++>Advanced プロパティ ページを選択します。

  3. [特定の警告を無効にする] プロパティを編集して 4996 を追加します。 [OK] をクリックして変更を適用します。

プリプロセッサ マクロを使用して警告を無効にする

プリプロセッサ マクロを使用して、ライブラリで使用される非推奨の警告の特定のクラスをオフにすることもできます。 これらのマクロについては、以下で説明します。

Visual Studio でプリプロセッサ マクロを定義するには:

  1. プロジェクトの [プロパティ ページ] ダイアログを開きます。 [プロパティ ページ] ダイアログの使用方法の詳細については、プロパティ ページを参照してください。

  2. C/C++ > プリプロセッサ>構成プロパティを展開します。

  3. プリプロセッサ定義プロパティで、マクロ名を追加します。 [ OK] を 選択して保存し、プロジェクトをリビルドします。

特定のソース ファイルでのみマクロを定義するには、ヘッダー ファイルを含む行の前に #define EXAMPLE_MACRO_NAME などの行を追加します。

C4996 の警告とエラーの一般的な原因を次に示します。

POSIX 関数名

この項目の POSIX 名は非推奨です。 代わりに、ISO C および C++ 準拠の名前 ( new-name) を使用します。 詳細については、オンライン ヘルプを参照してください。

Microsoft は、予約済みおよびグローバル実装定義名に対する C99 および C++03 の制約に準拠するように、CRT の POSIX および Microsoft 固有のライブラリ関数の名前を変更しました。 名前のみが非推奨となり、関数自体は非推奨です。 ほとんどの場合、関数名に先頭のアンダースコアが追加され、準拠する名前が作成されました。 コンパイラは、元の関数名に対して非推奨の警告を発行し、推奨される名前を提案します。

この問題を解決するには、通常、代わりに推奨される関数名を使用するようにコードを変更することをお勧めします。 ただし、更新された名前は Microsoft 固有です。 移植性の理由から既存の関数名を使用する必要がある場合は、これらの警告をオフにすることができます。 関数は、元の名前でライブラリで引き続き使用できます。

これらの関数の非推奨の警告をオフにするには、プリプロセッサ マクロ _CRT_NONSTDC_NO_WARNINGSを定義します。 オプション /D_CRT_NONSTDC_NO_WARNINGSを含めることで、コマンド ラインでこのマクロを定義できます。

安全でない CRT ライブラリ関数

この関数または変数は安全でない可能性があります。 代わりに safe-version を使用することを検討してください。 非推奨を無効にするには、_CRT_SECURE_NO_WARNINGSを使用します。 詳細については、オンライン ヘルプを参照してください。

セキュリティで保護されたバージョンが利用可能になるため、一部の CRT および C++ 標準ライブラリの関数とグローバルは非推奨になりました。 非推奨の関数のほとんどは、バッファーへの未チェックの読み取りまたは書き込みアクセスを許可します。 不正使用は、深刻なセキュリティ問題につながる可能性があります。 コンパイラは、これらの関数に対して非推奨の警告を発行し、推奨される関数を提案します。

この問題を解決するには、代わりに関数または変数 safe-version を使用することをお勧めします。 移植性や下位互換性の理由から、できない場合があります。 コードでバッファーの上書きまたはオーバー読み取りが行われないことを慎重に確認します。 その後、警告をオフにすることができます。

CRT でこれらの関数の非推奨の警告をオフにするには、 _CRT_SECURE_NO_WARNINGSを定義します。

非推奨のグローバル変数に関する警告をオフにするには、 _CRT_SECURE_NO_WARNINGS_GLOBALSを定義します。

これらの非推奨の関数とグローバルの詳細については、「 CRT および 安全なライブラリのセキュリティ機能: C++ 標準ライブラリ」を参照してください

安全でない標準ライブラリ関数

'std:: function_name ::_Unchecked_iterators::_Deprecate' std:: 安全でない可能性のあるパラメーターを使用して function_name します。この呼び出しは呼び出し元に依存して、渡された値が正しいことを確認します。 この警告を無効にするには、-D_SCL_SECURE_NO_WARNINGS を使用します。 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 では、いくつかの標準ライブラリ アルゴリズムが "デュアルレンジ" バージョンに更新されました。 デュアル範囲バージョンを使用する場合、2 番目の範囲では必要な境界チェックが提供されます。

// 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 関数と変数

この関数または変数は、新しいライブラリまたはオペレーティング システムの機能に置き換わりました。 代わりに new_item を使用することを検討してください。 詳細については、オンライン ヘルプを参照してください。

一部のライブラリ関数とグローバル変数は非推奨とされています。 これらの関数と変数は、ライブラリの将来のバージョンで削除される可能性があります。 コンパイラは、これらの項目に対して非推奨の警告を発行し、推奨される代替手段を提案します。

この問題を解決するには、推奨される関数または変数を使用するようにコードを変更することをお勧めします。

これらの項目の非推奨の警告をオフにするには、 _CRT_OBSOLETE_NO_WARNINGSを定義します。 詳細については、非推奨の関数または変数のドキュメントを参照してください。

CLR コードでのエラーのマーシャリング

C4996 は、CLR マーシャリング ライブラリを使用する場合にも発生します。 この場合、C4996 は警告ではなくエラーです。 このエラーは、 marshal_as を使用して、 marshal_context クラスを必要とする 2 つのデータ型間で変換するときに発生します。 マーシャリング ライブラリで変換がサポートされていない場合にも、このエラーが発生する可能性があります。 マーシャリング ライブラリの詳細については、「 C++ でのマーシャリングの概要」を参照してください

この例では、マーシャリング ライブラリで System::String から const char *に変換するコンテキストが必要であるため、C4996 が生成されます。

// 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 は 2 つの場所で生成されます。1 つは非推奨の関数が宣言されている行用で、1 つは関数が使用される行用です。

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