C언어 C4996 _CRT_SECURE_NO_WARNINGS 해결 방법

C언어 프로그래밍 입문 시에 가장 많이 사용하는 함수 중에 scanf() 함수의 경우 치명적인 문제가 있습니다. 우선 간단 코드를 보겠습니다.

 

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[11];

    scanf("%s", str);
    printf("%s", str);
    getchar();
}

 

scanf() 함수를 이용해서 문자열을 입력받아 그대로 출력하는 프로그램입니다. 오타를 치지 않는 한 버그가 있으래야 있을 수 없는 코드입니다. 단, 이 코드에 치명적인 문제가 있습니다. scanf() 함수의 경우 입력받는 문자열의 크기를 검사하지 않습니다. 그러면 충분히 크게 배열의 크기를 1000 정도로 하면 되지 않느냐 할 것입니다. 상관은 없습니다. 문제는 이 세상의 누구도 1000개를 입력하지 않는다면요. 어차피 요즘 PC 환경은 자원이 풍부해서 예전과 같이 메모리가 낭비되네 하는 예기는 별로 설득력이 없어지고 있습니다. 그런데 장난이던 아니던 누군가는 하겠지요. "1000개 이하로 입력하세요"라고 메시지를 띄우면 그 이상 입력해보고 싶은 것이 사람 마음이기도 하고요. 그러면 10,000개로 할까요, 아니면 100,000개로 할까요? 세상은 넓고 이상한 사람도 많아서 무작정 늘리는 것은 문제가 있습니다. 그래서 Visual Studio에서는 scanf() 함수를 사용할 경우에는 아래와 같은 경고 메시지가 뜨게 됩니다.

 

<그림1> scanf() 함수를 사용할 경우 경고 메시지

 

우선 경고 메시지를 없애는 방법에 대해서 알려드립니다.  

아래의 코드를 첫 줄에 입력 :  
방법 1 : #define _CRT_SECURE_NO_WARNINGS  
방법 2: #pragma warning(disable:4996)


위에 왜 문제가 되는지는 간단하게 썼지만 여기서 좀 더 자세하게 확인해 보겠습니다. 위의 메시지는 꼭 scanf() 함수만 나오는 것은 아니고, 기타 scanf()와 같이 사용자 입력 실수를 막아 줄 수 없는 함수를 사용할 경우에 뜨게 됩니다. 또한 위에서는 경고 메시지이므로 프로그램을 실행할 수는 있는데 설정에 따라서는 에러로 처리되기도 합니다. 에러로 할지 경고로 할지는 아래의 방법으로 변경할 수 있습니다.  

Visual Studio 메뉴에서 properties -> C/C++ -> General -> SDL checks -> Yes(/sdl)을 선택하게 되면 에러로 처리되고 No(/sdl-)로 하면 경고로 처리됩니다.  

우선 진짜로 어떤 문제가 생기는지 보겠습니다. 위의 코드를 보면 10개의 문자열을 입력받을 수 있습니다. 선언은 str[11]인데 왜 10개냐면 C언어에서 문자열의 끝은 0x00으로 알 수 있는데 이 값을 저장할 공간이 있어야 하므로 실제 문자열 크기는 str 크기 -1이 됩니다. 

<그림2> 10개 이상의 문자를 입력
<그림3> 런타임 에러 발생

<그림 2>와 같이 10개 이상의 문자(숫자이지만 %s이므로 문자로 처리)를 입력하면 런타임 에러가 발생합니다. 이러한 문제를 해결하기 위해서 scanf_s() 함수를 제공하고 있습니다. 단, 이 함수는 Visual Studio에서 제공하는 것으로 호환성은 떨어집니다. 우선 수정된 코드는 아래와 같습니다. 

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[11];

    scanf_s("%s", str, sizeof(str));
    printf("%s", str);
    getchar();
}

 

scanf_s() 함수의 경우 마지막 인자에 배열의 크기를 주게 되어 있습니다. 만약 10개 이상의 문자를 입력하면 아래 <그림 4>와 같이 배열에 문자열을 저장하지 않습니다.

<그림4> 배열크기보다 클 경우 저장하지 않음

 

여기서는 단순 예를 보여준것이고, 실제 프로그램에서는 사용자에게 다시 입력하라는 에러 처리는 해야 합니다. scanf_s() 함수가 하는 역할은 배열 크기보다 많은 글자가 입력되어서 비정상 종료가 되는 것을 막아주는 것입니다.

댓글(0)

Designed by JB FACTORY