세그멘테이션 오류

세그멘테이션 오류 또는 세그멘테이션 결함(Segmentation Fault, Segmentation Violation)은 컴퓨터 소프트웨어의 실행 중에 일어날 수 있는 특수한 오류이다. 세그멘테이션 위반, 세그멘테이션 실패라고도 하며, 세그폴트(Segfault)로 줄여서 쓰기도 한다. 세그멘테이션 오류는 프로그램이 허용되지 않은 메모리 영역에 접근을 시도하거나, 허용되지 않은 방법으로 메모리 영역에 접근을 시도할 경우 발생한다. (예를 들어, 읽기 전용 영역에 어떤 내용을 쓰려고 시도하거나, 운영 체제에서 사용하는 영역에 다른 내용을 덮어쓰려 하는 경우) 모토로라 68000 등의 프로세서 기반 시스템들은 이러한 오류를 주소나 버스 오류로 취급하는 경향이 있다.

세그멘테이션은 운영 체제에서 사용하는 메모리 관리 및 보호의 한 기법이다. 이것은 페이징으로 대부분 대체되었지만, 세그멘테이션이라는 용어는 '세그멘테이션 오류'라는 용어에서 볼 수 있듯이 여전히 사용되고 있다. 주로 사용되는 메모리 관리 정책이 페이징이지만 몇몇 운영 체제는 여전히 일부 논리 레벨에서 세그멘테이션을 사용하기도 한다.

유닉스 계열 운영 체제들에서는, 잘못된 메모리에 접근하는 프로세스는 SIGSEGV 신호를 받는다. 마이크로소프트 윈도우에서는, 잘못된 메모리에 접근하는 프로세스는 STATUS_ACCESS_VIOLATION 예외 처리를 받는다.

컴파일은 잘 되는데 실행에서 오류가 나는 경우가 대부분이다.

예제 
다음은 메모리 보호를 사용하는 플랫폼에서 세그멘테이션 오류를 만드는 ANSI C 코드이다.
     const char *s = "hello world";
     *s = 'H';

위 코드를 포함하는 프로그램이 컴파일되면, 문자열 "hello world"는 이 프로그램에서 읽기 전용이 된다. 프로그램이 로드되었을 때, 운영 체제는 이 문자열과 상수 데이터를 메모리의 읽기 전용 세그먼트에 배치한다. 프로그램이 실행되면, 변수 's'는 이 문자열의 위치를 가리키게 되고, 'H'라는 문자열을 변수 s를 통해 메모리에 기록하려는 시도는 곧 세그멘테이션 오류을 일으키게 된다.

OpenBSD 4.0에서 이런 프로그램을 컴파일하고 실행하면 다음과 같은 런타임 오류가 발생한다.

 $ gcc segfault.c -g -o segfault
 $ ./segfault
 Segmentation fault

GDB(GNU 디버거)를 통한 추적 결과:

 Program received signal SIGSEGV, Segmentation fault.
 0x1c0005c2 in main () at segfault.c:6
 6               *s = 'H';

대조적으로, GNU/Linux에서 GCC 4.1.1로 같은 시도를 하면 컴파일 에러가 발생한다.

 $ gcc segfault.c -g -o segfault
 segfault.c: In function ‘main’:
 segfault.c:4: error: assignment of read-only location

즉 세그멘테이션 경고가 발생하는 조건이나 그것을 사용자에게 알려주는 방법은 운영 체제에 따라서도 다르다.

널 포인터 역참조(주소 '0'을 참조하는 포인터인 널 포인터를 통한 읽기나 쓰기로, C에서 '아무것도 가리키지 않는 포인터'를 나타내기 위해서 또는 오류 지시자로 사용)는 흔히 일어나는 오류이기 때문에, 대부분의 운영 체제는 메모리의 첫 페이지(주소 0에서 시작하는)를 살피며, 따라서 여기에 접근하면 세그멘테이션 오류이 발생한다.

 int* ptr = (int*) 0x00000000;
 *ptr = 1;

위 샘플 코드는 메모리 주소 0x00000000에 접근하는 포인터를 생성하고, 그 곳에 값을 할당하려고 시도한다. 이런 행동은 많은 컴파일러에서 세그멘테이션 오류을 일으킨다.

같이 보기 
 버퍼 오버플로
 버스 에러
 코어 덤프

외부 링크 
 FAQS.ORG QA 내용

컴퓨터 오류