컴파일러 경고(수준 3) C4996
코드는 사용되지 않는 것으로 표시된 함수, 클래스 멤버, 변수 또는 typedef를사용합니다. 기호는 __declspec(deprecated)
한정자 또는 C++14 [[deprecated]]
특성을 사용하여 더 이상 사용되지 않습니다. 실제 C4996 경고 메시지는 선언의 deprecated
한정자 또는 특성에 의해 지정됩니다.
Important
이 경고는 항상 기호를 선언하는 헤더 파일 작성자의 의도적인 메시지입니다. 결과를 이해하지 않고 사용되지 않는 기호를 사용하지 마세요.
설명
Visual Studio 라이브러리의 많은 함수, 멤버 함수, 함수 템플릿 및 전역 변수는 더 이상 사용되지 않습니다. POSIX 및 Microsoft 관련 함수와 같은 일부 함수는 이제 다른 기본 설정 이름을 가지므로 더 이상 사용되지 않습니다. 일부 C 런타임 라이브러리 함수는 안전하지 않고 보다 안전한 변형을 가지므로 더 이상 사용되지 않습니다. 다른 항목들은 사용되지 않으므로 더 이상 사용되지 않습니다. 사용 중단 메시지에는 일반적으로 사용되지 않는 함수 또는 전역 변수에 대한 제안된 대체 항목이 포함됩니다.
/sdl
(추가 보안 검사 사용) 컴파일러 옵션은 이 경고를 오류로 승격합니다.
경고 끄기
C4996 문제를 해결하려면 일반적으로 코드를 변경하는 것이 좋습니다. 대신 제안된 함수 및 전역 변수를 사용합니다. 이식성을 위해 기존 함수 또는 변수를 사용해야 하는 경우 경고를 해제할 수 있습니다.
특정 코드 줄에 대한 경고 끄기
특정 코드 줄에 대한 경고를 끄려면 warning
pragma, #pragma warning(suppress : 4996)
를 사용합니다.
파일 내에서 경고 끄기
다음의 모든 항목에 대해 파일 내에서 경고를 해제하려면 경고 pragma #pragma warning(disable : 4996)
를 사용합니다.
명령줄 빌드에서 경고 끄기
명령줄 빌드에서 전역적으로 경고를 끄려면 /wd4996
명령줄 옵션을 사용합니다.
Visual Studio에서 프로젝트에 대한 경고 끄기
Visual Studio IDE에서 전체 프로젝트에 대한 경고를 해제하려면 다음을 수행합니다.
프로젝트에 대한 속성 페이지 대화를 엽니다. 속성 페이지 대화 상자를 사용하는 방법에 대한 자세한 내용은 속성 페이지를 참조하세요.
구성 속성>C/C++>고급 속성 페이지를 선택합니다.
특정 경고 사용 안 함 속성을 편집하여
4996
을(를) 추가합니다. 확인을 선택하여 변경 내용을 적용합니다.
전처리기 매크로를 사용하여 경고 사용 안 함
전처리기 매크로를 사용하여 라이브러리에 사용되는 특정 사용 중단 경고 클래스를 해제할 수도 있습니다. 이러한 매크로는 아래에 설명되어 있습니다.
Visual Studio에서 전처리기 매크로를 정의하려면 다음을 수행합니다.
프로젝트에 대한 속성 페이지 대화를 엽니다. 속성 페이지 대화 상자를 사용하는 방법에 대한 자세한 내용은 속성 페이지를 참조하세요.
구성 속성 > C/C++ > 전처리기를 차례로 확장합니다.
전처리기 정의 속성에서 매크로 이름을 추가합니다. 확인 을 선택하여 저장한 다음 프로젝트를 다시 빌드합니다.
특정 원본 파일에서만 이 매크로를 정의하려면 헤더 파일이 포함된 모든 줄 앞에 #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.
Microsoft는 예약된 및 전역 구현 정의 이름에 대한 C99 및 C++03 제약 조건을 준수하도록 CRT에서 일부 POSIX 및 Microsoft 관련 라이브러리 함수의 이름을 변경했습니다. 이름만 사용되지 않고 함수 자체는 사용됩니다. 대부분의 경우 함수 이름에 선행 밑줄이 추가되어 준수 이름을 만듭니다. 컴파일러는 원래 함수 이름에 대해 사용 중단 경고를 실행하고 기본 설정 이름을 제안합니다.
이 문제를 해결하려면 일반적으로 제안된 함수 이름을 대신 사용하도록 코드를 변경하는 것이 좋습니다. 그러나 업데이트된 이름은 Microsoft 전용입니다. 이식성을 위해 기존 함수 이름을 사용해야 하는 경우 이러한 경고를 해제할 수 있습니다. 함수는 원래 이름 아래 라이브러리에서 계속 사용할 수 있습니다.
이러한 함수에 대한 사용 중단 경고를 끄려면 전처리기 매크로 _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.
Microsoft는 더 안전한 버전을 사용할 수 있기 때문에 일부 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 코드
보안상의 이유로 사용되지 않는 MFC 또는 ATL 함수를 사용하는 경우 C4996이 발생할 수 있습니다.
이 문제를 해결하려면 업데이트된 함수를 대신 사용하도록 코드를 변경하는 것이 좋습니다.
이러한 경고를 표시하지 않는 방법에 대한 자세한 내용은 _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 코드의 마샬링 오류
CLR 마샬링 라이브러리를 사용하는 경우에도 C4996이 발생할 수 있습니다. 이 경우 C4996은 경고가 아니라 오류입니다. 이 오류는 marshal_context
클래스가 필요한 두 데이터 형식 간의 변환을 위해 marshal_as
를 사용할 때 발생합니다. 마샬링 라이브러리가 변환을 지원하지 않을 때 이 오류가 발생할 수 있습니다. 마샬링 라이브러리에 대한 자세한 내용은 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은 사용되지 않는 함수가 선언된 줄에 대해 하나씩, 함수가 사용되는 줄에 대해 하나씩 두 위치에서 생성됩니다.
// 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
}