古いC/C++コードを Visual Studio でビルドすると、strcpy や sprintf などに対して C4996 が出ることがあります。/WX(警告をエラーとして扱う)を有効にしているプロジェクトでは、スクリーンショットのように Error List 上でそのまま「エラー」として止まります。
error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
対象になるのは strcpy、sprintf、fopen などです。Visual Studio では通常は warning C4996 として出ますが、/WX を有効にしているプロジェクトでは error C4996 として扱われ、ビルドが止まります。
この記事では、C4996 が出る理由 と、書き換えて直す方法、抑制して進める方法 の使い分けを整理します。
なぜ strcpy は「危険 (unsafe)」なのか?

昔ながらの関数(特に文字列操作系)には、「バッファの最大サイズを受け取る引数がない」 という設計上の弱点があります。
char dest[10];
strcpy(dest, "This string is much larger than 10 bytes!"); // バッファサイズを超える書き込み
関数は dest の大きさがたった10バイトであることを知らないため、延々とメモリ領域を上書きし続け、隣接する大切なデータやプログラム状態を破壊してしまいます(バッファオーバーラン脆弱性)。
Microsoftはこれを深刻なセキュリティホールと重く見て、Visual Studio 2005以降、これらの旧関数に軒並み「非推奨 (C4996)」のマークを付けました。
これを解決するためのアプローチは大きく2つあります。
アプローチA: 安全な代替関数(_s系への書き換え)
Microsoftが推奨している「正しい」解決策です。This function or variable may be unsafe. Consider using strcpy_s instead. と言われている通り、関数名の末尾に _s (Secure) が付いた代替関数に置き換えます。
1. 新しい関数の書き方
_s 系の関数は、引数に「バッファの最大サイズ」を渡す仕様になっています。これにより、バッファオーバーランが発生する前にエラーとして安全に弾くことができます。
【strcpy の場合】
// ❌ 旧(危険)
char dest[10];
strcpy(dest, src);
// ⭕ 新(安全)
char dest[10];
// 第2引数にバッファサイズ(要素数)を追加
strcpy_s(dest, _countof(dest), src);
【sprintf の場合】
// ❌ 旧(危険)
char buf[100];
sprintf(buf, "Value = %d", val);
// ⭕ 新(安全)
char buf[100];
sprintf_s(buf, _countof(buf), "Value = %d", val);
【fopen の場合】
// ❌ 旧(危険)
FILE* fp = fopen("test.txt", "w");
// ⭕ 新(安全)
FILE* fp;
errno_t err = fopen_s(&fp, "test.txt", "w"); // ポインタのポインタを渡す仕様変更に注意
if (err != 0) { /* エラー処理 */ }
2. MFCなら CString を使おう!
MFC プロジェクトでは、C言語ライクな char 配列操作を減らし、CString を使う方が管理しやすくなります。C4996 の対象になる関数を避けやすくなり、文字列操作も整理しやすくなります。
// ⭕ MFCの正しい姿
CString strDest;
strDest.Format(_T("Value = %d"), val); // 自動拡張されるので安全!
アプローチB: 警告を抑制する
ただし、既存コードの量が多い場合や、サードパーティ製ライブラリの内部で C4996 が出ている場合は、すぐにすべてを書き換えられないこともあります。
その場合は、警告を抑制する設定を入れてビルドを先に通します。メッセージにも To disable deprecation, use _CRT_SECURE_NO_WARNINGS. と書かれている通り、_CRT_SECURE_NO_WARNINGS を定義すると C4996 は抑制できます。
方法1: プロジェクト全体で一括抑制する(推奨)

- ソリューションエクスプローラーでプロジェクトを右クリックして「プロパティ」を開きます。
- 構成プロパティ >
C/C++>プリプロセッサを開きます。 - 「プリプロセッサの定義」に以下の一文を追加します(既存の文字に
;をつけて追記)。
_CRT_SECURE_NO_WARNINGS - 「適用」→「OK」を押してリビルドします。
これで、プロジェクト全体のC4996警告が消えます。
方法2: 特定のファイルだけピンポイントで抑制する
もし「自分が書くコードは _s を使って綺麗に保ちたいが、外部から持ってきたこの old_lib.cpp だけは警告を消したい」という場合は、該当ファイルの先頭(#include より上)に以下のマクロを定義します。
// stdafx.h / pch.h より上に書くか、ファイルの先頭に書く
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable: 4996)
#include "stdafx.h"
#include <string.h>
// ...
#pragma warning(disable: 4996) は、特定のファイルやブロック内だけで 4996 を無効化する方法です。
まとめ:どう対応するべきか?
- [ ] 新規で書くコードでは、
strcpy_sやCStringを使います。 - [ ] MFCプロジェクトでは、可能な範囲で C言語関数から離れ、
CStringのメソッド群(Format, Left, Right等)へ置き換えます。 - [ ] 巨大なレガシーシステムの移行中や、外部ライブラリを組み込む際は、
_CRT_SECURE_NO_WARNINGSをプリプロセッサに定義して一時的に抑制します。
C4996 は、古い C 言語系関数の扱いを見直すきっかけになります。新規コードでは安全な関数や CString へ置き換え、既存コードや外部ライブラリでは必要に応じて抑制を使い分けてください。
