살아가는 이야기

Visual Studio 2005: Run-Time Check Failure #2 - Stack around the variable 'n' was corrupted. 본문

컴퓨터, 풀어그림

Visual Studio 2005: Run-Time Check Failure #2 - Stack around the variable 'n' was corrupted.

우균 2010. 3. 26. 13:23
Visual Studio 2005에서 이 글 제목과 같은 "Run-Time Check Failure #2 - Stack around the variable 'n' was corrupted."라는 메시지가 나타났다. 다른 컴파일러를 이용하면 잘 작동하던 프로그램이었기 때문에 더욱 더 당황하게 되었다. 원인은 무엇일까? 웹 페이지를 찾아 보니 이것 때문에 고생한 사람들이 많았던 것 같다. 페이지 열 개가 넘는 검색 결과! 그런데 원인은 무엇일까?

원인은 포인터 문제다.
지역 변수(배열 변수든 클래스 변수든 상관 없음)의 주소(포인터)를 이용하여 그 변수에 무엇인가를 기록하려고 할 때, 타입 오류로 인해서 실제 변수에 할당된 크기보다 더 많은 부분에 기록하는 경우에 이런 오류 메시지가 나타난다. 결과적으로 지역변수 스택이 망가지는 것이다.

다음 예를 보자.

#include <cstdio>
const int MAX = 80;
int main()
{
    char word[MAX], n = 0, count = 0;
    FILE *in = stdin, *out = stdout;
    while (fscanf(in, "%s", word) == 1) {
        if (sscanf(word, "%d", &n) == 1)
            count++;
    }
    fprintf(out, "count = %d\n", count);
}


위 프로그램은 공백으로 구별된 단어들을 읽고, 거기에 십진수로 시작되는 부분이 있는 단어들을 하나씩 세는 프로그램이다. 입력이 영어 단어와 십진 정수로만 되어 있다면, 십진 정수를 세는 프로그램이다. 소수가 입력으로 있으면 이 부분은 세지 않는다.

사설이 길었지만 위 프로그램의 경우에 Visual Studio 2005에서 제목과 같은 오류가 발생한다. 원인은 무엇일까? sscanf의 앞 뒤를 살펴보고 여러 코드를 삽입해 봐도 어떤 오류도 발견할 수 없다. if문의 안쪽에 word를 출력하도록 고치면 문제의 원인을 조금은 파악할 수 있다. word가 제대로 출력되지 않기 때문이다.

오류 메시지에 나온 대로 문제의 원인은 n이다. 여기서는 n의 공간을 절약하기 위해서 n을 char 타입으로 정했다. 그런데 sscanf에서는 n을 int 타입이라고 가정하고 n에 값을 넣는다. 따라서 n의 범위를 벗어나서 값을 넣으려는 시도를 하는 것이다.

포인터가 C 프로그램 오류 원인의 대부분이라고 하더니만, 정말 포인터의 무시무시함을 실감하지 않을 수 없다.
Comments