Segmentation Fault

이재원·2024년 3월 12일
0
  • 세그먼테이션(segmentation) 메모리 관리는 프로그램의 메모리 공간을 여러 개의 세그먼트로 나누어 관리하는 기법이다.
  • 프로그램의 코드, 데이터, 스택과 같은 논리적인 부분을 별도의 세그먼트로 분리하여 메모리에 배치함으로써 더 유연한 메모리 관리를 가능하게 한다.
  • 세그먼트는 기본(base) 주소와 한계(bounds) 주소를 갖으며, 이를 통해 세그먼트의 시작 위치와 크기를 정의
  • 세그먼테이션은 프로그램이 사용하는 논리적 메모리 공간을 물리적 메모리에 비연속적으로 매핑할 수 있게 해, 메모리 사용의 효율성을 높이고 프로세스 간의 메모리 보호를 강화한다.

세그먼테이션의 핵심 이점
1. 세그먼테이션은 각 세그먼트에 대해 접근 제어 정보를 제공하여, 특정 세그먼트의 읽기, 쓰기, 실행 권한을 제어할 수 있다.

  • 운영 체제는 프로세스가 서로의 메모리 영역에 무단으로 접근하는 것을 방지할 수 있다. 또한, 코드 세그먼트 같이 변경되지 않는 데이터는 여러 프로세스 간에 공유할 수 있어 메모리 사용을 최적화한다.
  1. 프로그램의 각 논리적 부분을 별도의 세그먼트로 관리함으로써, 세그먼트의 크기를 동적으로 조절하거나, 필요에 따라 메모리의 다른 부분으로 이동시키기가 용이하다. 이는 프로그램의 메모리 요구 사항이 변할 때 더 높은 메모리 사용 효율을 가능하게 한다.

단점
세그먼테이션은 외부 단편화(external fragmentation)라는 문제를 내포하고 있다. 외부 단편화는 메모리에 할당되지 않은 작은 공간들이 산재하게 되어, 충분한 전체 메모리가 있음에도 불구하고 큰 메모리 요청을 만족시키지 못하는 상황을 의미한다. 이를 해결하기 위해, 운영 체제는 주기적으로 메모리를 압축하거나, 효율적인 메모리 할당 알고리즘을 사용하여 이 문제를 최소화하려고 노력한다.

세그먼테이션은 과거 많은 시스템에서 널리 사용되었으나, 외부 단편화 문제와 관리 복잡성 때문에 현대 운영 체제에서는 페이지 기반의 메모리 관리 기법이 더 일반적으로 사용된다. 그럼에도 불구하고, 세그먼테이션은 메모리 관리의 중요한 개념 중 하나로서, 특정 상황에서 여전히 유용하게 사용될 수 있다.

  • Segmentation Fault(세그멘테이션 폴트)는 메모리 접근 오류의 일종으로, 프로그램이 잘못된 메모리 주소에 접근할 때 발생한다.
  • 세그멘테이션 위반, 세그멘테이션 실패라고도 하며, 세그폴트(Segfault)로 줄여서 쓰기도 한다.
  • 세그먼티드 메모리 관리를 사용하는 컴퓨터 시스템에서 유래했으나, 세그멘테이션을 지원하지 않는 시스템에서도 널리 사용된다.
  • 잘못된 메모리 주소에 접근하려고 할 때, 하드웨어는 주소가 유효하지 않음을 감지하고 운영 체제로 트랩(trap)을 발생시킨다. 이때 운영 체제는 해당 프로세스를 종료시키는 것이 일반적이다. 이는 프로그램이 예상치 못한 메모리 영역을 침범하여 시스템의 안정성이나 다른 프로세스에 영향을 줄 수 있기 때문이다 .

대표적인 상황

  • 유효하지 않은 포인터를 역참조하는 경우, 배열의 범위를 초과하여 접근하려고 하는 경우, 스택 오버플로우 등이 있다.
  • 초기화되지 않은 포인터에 접근하거나, 프로그램의 데이터 영역에 속하지 않는 주소를 참조할 때 세그멘테이션 폴트가 발생
  • 프로그램이 허용되지 않은 메모리 영역에 접근을 시도하거나, 허용되지 않은 방법으로 메모리 영역에 접근을 시도할 경우 발생
    -> 읽기 전용 영역에 어떤 내용을 쓰려고 시도하거나, 운영 체제에서 사용하는 영역에 다른 내용을 덮어쓰려 하는 경우

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

	 const char *s = "hello world";
     *s = 'H';
 $ gcc segfault.c -g -o segfault
 $ ./segfault
 Segmentation fault
	int* ptr = (int*) 0x00000000;
	*ptr = 1;

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

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

주로 사용되는 메모리 관리 정책이 페이징이지만 몇몇 운영 체제는 여전히 일부 논리 레벨에서 세그멘테이션을 사용하기도 한다

문제 원인을 파악하기 위해
코어 덤프(core dump)를 분석하거나 디버거를 사용해 문제가 발생한 시점의 스택 트레이스(stack trace)를 검토할 수 있다.

세그멘테이션 폴트는 프로그램의 신뢰성과 안정성을 위협할 수 있으므로, 포인터 사용 시 유효성 검사를 수행하고, 배열 접근 시 인덱스 범위를 체크하는 등의 예방 조치를 취하는 것이 중요하다.

출처
https://ko.wikipedia.org/wiki/%EC%84%B8%EA%B7%B8%EB%A9%98%ED%85%8C%EC%9D%B4%EC%85%98_%EC%98%A4%EB%A5%98

profile
최고가 되기 위한 여정

0개의 댓글