Computer_Language/C

[C] 인덱스 검사(경계 검사)에 대하여

Joo-Topia 2019. 8. 31. 16:47

오늘은 인덱스 검사에 대해 공부를 했다.

많은 사람들이 경계 검사와 인덱스 검사를 혼용해서 사용하는데, 엄밀히 따지면 경계 검사가 더 포괄적인 단어이다. (통상적으로는 경계 검사를 인덱스 검사라고 부른다고 한다 - 참고)

 

오늘 공부한 내용은 경계 검사 중 인덱스 검사에 대해 공부를 했다.

 

인덱스 검사란


접근할 배열의 인덱스가 정의했던 경계 안에 존재하는지 확인하는 검사이다.

C언어는 빠른 실행 속도를 위해 경계 검사를 자동으로 수행하지 않는다. 컴퓨터 언어를 공부한 지 1년 반만에 알았지만 중요한 개념이니 제대로 정리를 해보자.

프로그래밍을 글로 배우기는 쉽지 않으니 적절한 예시를 만들어보았다.

#include <stdio.h>

int main() {
    int i, a[40];

    for (i = 0; i < 40; i++) {
        a[i] = i;
    }

    for (i = 0; i < 90; i += 10) {
        printf("a[%d]의 헥사 값은 : 0x%08x\n", i, a[i]);
    }

    return 0;
}

결과

 

예제를 천천히 살펴보며 머리에 집어넣어보자.

a[0] ~ a[39]에는 0~39까지의 숫자를 대입했고, 출력 결과를 보면 a[0], a[10], a[20], a[30]까지는 입력한 대로 출력이 되었다.

"인덱스가 40이상일때 왜 오류가 안 나고 이상한 값들이 출력될까?" <- 이 생각이 인덱스 검사에 대한 공부의 시작이었다.

위에서 언급했듯이 C언어는 인덱스 검사를 자동으로 수행하지 않기 때문에 잘못된 배열에 접근해도 접근 명령을 그대로로 수행한 것이다.

그림으로 정리해보았다.

main문 안에서 선언한 배열은 메모리에 연속적으로 할당되는데, a[40]으로 접근하게 되는경우 메모리 구조상 a[39]다음에 위치한 데이터를 반환하게 된다. 만약 인덱스 검사를 수행했다면 a[40]으로 접근하려는 순간 프로그램이 종료되지만, 검사를 하지 않았기 때문에 가능한 결과이다.

 

 

C언어의 인덱스 검사


나는 분명 잘못된 인덱스 접근으로 Segmentation Faul 오류가 발생했던 기억이 있다. C는 인덱스 검사를 하지 않는다고 했는데..

호기심에 한번 다음 코드를 실행시켜 보았다.

#include <stdio.h>

int main() {
    int i, a[40];

    for (i = 0; i < 40; i++) {
        a[i] = i;
    }

    for (i = 0; i < 500000; i += 10) {
        printf("a[%d]의 헥사 값은 : 0x%08x\n", i, a[i]);
    }
	
    return 0;
}

결과 (실행할 때 마다 결과가 조금 씩 다름)

코드상에서 인덱스는 0에서 50만까지 정의했는데, 특정 인덱스에 도달하자 프로그램이 죽고 Segmentation Faul 오류를 발생시켰다. 

실행할 때마다 멈추는 위치도 다르고 너무 궁금해서 구글링을 해보니 이 경우는 운영 체제의 경계 검사(?)라고 한다. 공식적인 문서에 있는 내용은 아니기 때문에 "스택에 할당된 메모리를 초과할 경우"라고 이해했다. 예를 들면 스택이 계속 쌓여 heap 영역을 초과하는 상황이다.

속도를 위해 인덱스 검사를 수행하지 않지만, 정말 치명적인 버그는 방지해 주는 것 같다.

 

정리


오늘은 다루기 애매한 내용이어서 그런지 정리도 잘 안된 것 같다..

결론은 "C와 같이 인덱스 검사를 수행하지 않는 언어에서는 프로그래밍할 때 주의하자"이다.

실무에서도 잘못된 인덱싱을 Segmentation Faul 오류가 발생하고 나서야 수정하는 경우가 빈번히 발생한다고 한다.

 

이상 오늘 공부 끝!