F.R.I.D.A.Y.

scanf()의 문제점 본문

DEV/C C++

scanf()의 문제점

F.R.I.D.A.Y. 2019. 6. 25. 20:05
반응형
 

VS ERROR C4996 : SDL 오류

오늘은 scanf() 함수와 같이 입출력 함수, 문자열 함수를 다룰 때 종종 발생하는 C4996에 대해 다뤄봅니다. 원인 원래는 문제없이 컴파일되는 것이 맞지만, scanf() 등의 함수에서 발생 가능한 잠재적 문제점으로..

pang2h.tistory.com

 위 C4996 경고가 발생했던 이유에 대해 알아보는 시간을 가져봅니다.


함수의 구조

 함수의 구조부터 확인합니다. 일단, 간단히 strlen() 함수를 가지고 예시를 들어보도록 합니다. 아래는 예시를 위해 직접 작성한 strlen()과 동일 기능을 하는 함수입니다.

int strlen(char* str){
    int count = 0;

    while(1){
        if (*str != 0) count++;
        else break;
        str++;
    }

    return count;
}

 위 코드는 인자로 받은 문자열을 처음부터 순서대로 NULL 문자의 위치를 찾아 반환합니다. 이 코드는 문제가 한 가지 존재합니다. 만일 NULL 문자가 인자로 전달받은 문자열에 존재하지 않는다면 어떤 일이 벌어질까요?

 

 아래 두 문자열을 비교해봅니다. NULL 문자를 기준으로 제어를 하니 첫 번째에 있는 NULL 문자가 포함된 문자열에선 우리가 작성한 strlen() 함수가 정상적으로 동작합니다.

 그러나 두 번째, NULL 문자가 존재하지 않는 문자열을 우리가 만든 strlen() 함수에 넣게 되면 예기치 못한 논리적 오류를 일으키게 됩니다. 이러한 문자열들은 결국 메모리의 한 공간에 존재하므로 이 문자열 앞뒤로 또 다른 데이터가 존재합니다.

 첫 번째 케이스는 NULL 문자(\0)가 존재하므로 함수가 정상 종료됩니다. 따라서 뒤따라오는 66, 67, 45,...라는 데이터를 세지 않습니다. 그러나 두 번째 케이스는 NULL 문자가 존재하지 않으므로 뒤따라오는 65, 66, 67, 45,... 을 세게 됩니다. 그러다 0이란 데이터를 만났을 때 종료가 되죠.

 원래 목적은 문자열의 길이를 구하려고 했는데 실제 문자열 길이를 구하지 못하게 되는 것이죠.

더보기

# \0을 작성하지 않아도 정상적으로 동작하는데요?!

 물론 그러실 확률이 높을 겁니다. 이 문제를 모르는 분들께선 디버그/릴리즈 모드를 모르실 것이라 생각합니다. 간단히 설명드리면 디버그 모드가 프로젝트를 처음 만들었을 때, 개발 중에 발생하는 문제들을 쉽게 해결할 수 있도록 부가 정보를 함께 처리하도록 컴파일하는 방식이라면, 릴리즈 방식은 개발이 끝난 프로그램을 일반 대중들에게 공개하기 위해 최적화를 진행하여 컴파일하는 방식입니다.

 디버그 모드는 프로그램 개발중의 효율을 위해 메모리를 할당받으면 주변 메모리를 추가로 할당받습니다. 즉, 완충지대를 형성해 할당받는 것이죠. 이 완충지대는 특정 값으로 초기화되어있기 때문에 문제가 생기지 않을 수 있습니다. 그러나 실제 배포용 프로그램 컴파일 모드인 릴리즈 모드는 이 완충지대를 형성하지 않기 때문에 문제가 발생합니다.

 달리 말하면 디버그 모드에서 정상 동작하는 프로그램이 릴리즈 모드에서 제대로 동작하지 않는다면 다시 작성해야하는 코드라는 것입니다.

 

# 2019.12.23. 추가


새로운 함수의 탄생

 이 문제를 이용해 허용되지 않는 공간에 접근해 해당 위치의 데이터를 읽거나 새로 작성하는 방법으로 시스템을 해킹합니다. scanf()와 같은 함수가 이러한 문제가 발생하기 때문에 새로운 함수가 생성되었는데, 이 문제를 해결한 함수가 바로 기존 함수 명 뒤에 _s가 붙은 scanf_s() 함수입니다. scanf_s()의 사용법을 보면 변수와 문자열의 최대 길이를 함께 인수로 넘기라고 합니다. 최대 길이가 바로 이 문제를 해결하는 보완점이 된 것입니다.

 

scanf_s 사용하기

매번 scanf_s를 사용하면서도 제대로 된 사용법을 몰라서 질문을 하는 분들이 많습니다. 그래서 이번 포스트에서는 scanf_s의 사용 방법에 대해 설명합니다. 1. scanf_s C언어에서 입력을 받는 표준 입력입니다...

pang2h.tistory.com

 scanf_s() 함수처럼 뒤에 _s가 붙은 함수들은 해당 길이를 정해주어야 합니다.


참고

 이 문제는 Windows OS에서는 막혀있습니다. 실습한다고 해서 뒤의 메모리를 불러올 수도 있겠지만 대부분 오류를 일으키거나 OS에서 예외처리를 진행합니다.

728x90
반응형

'DEV > C C++' 카테고리의 다른 글

malloc VS calloc  (1) 2019.10.28
키워드와 예약어  (0) 2019.08.08
함수 인자로 단항연산자 사용하기  (0) 2019.06.25
C 스타일의 문자열 관리 방식  (0) 2019.06.25
sizeof 연산자의 오용  (0) 2019.06.17
Comments