C의 분할 오류 또는 C++는 프로그램이 액세스 권한이 없는 메모리 위치에 액세스하려고 할 때 발생하는 오류입니다. 일반적으로 이 오류는 메모리 액세스를 위반했을 때 발생하며 일반 보호 오류의 일종입니다. 세그폴트 Segmentation Fault의 약자입니다.
그만큼 코어 덤프 프로그램 상태, 즉 메모리와 프로세서의 리소스를 기록하는 것을 말합니다. 존재하지 않는 메모리나 다른 프로세스에서 사용 중인 메모리에 액세스하려고 하면 분할 오류가 발생하여 코어 덤프가 발생합니다.
프로그램은 실행되는 동안 특정 메모리 영역에 액세스할 수 있습니다. 첫째, 스택은 각 함수에 대한 지역 변수를 보유하는 데 사용됩니다. 게다가 런타임에 메모리가 할당되어 힙에 저장될 수도 있습니다(C++의 새로운 기능이며 무료 매장 ). 프로그램이 접근하도록 허용된 유일한 메모리는 자신의 메모리(앞서 언급한 메모리)입니다. 해당 지역 외부의 액세스로 인해 분할 오류가 발생합니다.
세그먼트화 오류는 메모리 액세스로 인해 발생하는 특정 종류의 오류입니다. 당신의 것이 아니다 :
- 코드 조각이 메모리의 읽기 전용 위치나 해제된 메모리 블록에서 읽기 및 쓰기 작업을 수행하려고 하면 이를 분할 오류라고 합니다.
- 메모리 손상을 나타내는 오류입니다.
일반적인 분할 오류 시나리오
분할 오류에서는 프로그램이 액세스 권한이 없거나 존재하지 않는 메모리에 액세스하려고 시도합니다. 분할 오류를 일으킬 수 있는 몇 가지 일반적인 시나리오는 다음과 같습니다.
- 문자열 리터럴 수정
- 해제된 주소에 액세스
- 배열 외부 인덱스 경계에 액세스
- scanf()의 부적절한 사용
- 스택 오버플로
- 초기화되지 않은 포인터 역참조
1. 문자열 리터럴 수정
문자열 리터럴은 메모리의 읽기 전용 섹션에 저장됩니다. 이것이 *(str+1) = 'n' 행이 읽기 전용 메모리를 쓰려고 시도하기 때문에 아래 프로그램이 충돌할 수 있는 이유입니다(분할 오류 오류 제공).
예:
씨
// C program to demonstrate segmentation fault> // by modifying a string literal> #include> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation fault> // by modifying a string literal> #include> using> namespace> std;> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }> |
>
>
산출
시간 초과: 모니터링되는 명령이 코어를 덤프했습니다.
/bin/bash: 라인 1: 32 분할 오류 시간 초과 15초 ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in
자세한 내용은 C의 문자열 저장을 참조하세요.
2. 해제된 주소에 접근하기
아래 코드에서는 메모리 블록을 해제한 후 포인터 p가 역참조되는데, 이는 컴파일러에서 허용되지 않습니다. 이러한 포인터를 현수 포인터라고 하며 런타임 시 세그먼트 오류나 비정상적인 프로그램 종료를 생성합니다.
예:
씨
// C program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> #include> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(8);> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// core dump/segmentation fault> >// as now this statement is illegal> >*p = 110;> >printf>(>'%d'>, *p);> >return> 0;> }> |
객관적인 자바
>
>
C++
// C++ program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> using> namespace> std;> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(>sizeof>(>int>));> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// segmentation fault> >// as now this statement is illegal> >*p = 110;> >return> 0;> }> |
>
>
산출
Segmentation Fault>
3. 범위를 벗어난 배열 인덱스에 액세스
C 및 C++에서 범위를 벗어난 배열 인덱스에 액세스하면 분할 오류 또는 기타 정의되지 않은 동작이 발생할 수 있습니다. C 및 C++에는 배열에 대한 경계 검사가 없습니다. C++에서는 std::Vector::at() 메서드나 if() 문과 같은 컨테이너를 사용하면 범위를 벗어난 오류를 방지할 수 있습니다.
예:
씨
// C program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> int> main(>void>)> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> (0);> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> using> namespace> std;> int> main()> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> 0;> }> |
>
>
산출
Segmentation Faults>
4. scanf()의 부적절한 사용
scanf() 함수는 변수의 주소를 입력으로 예상합니다. 여기 이 프로그램에서 n은 값 2를 취하고 주소를 1000으로 가정합니다. n을 scanf()에 전달하면 STDIN에서 가져온 입력은 대신 1000이어야 하는 잘못된 메모리 2에 배치됩니다. 이로 인해 메모리 손상이 발생하여 분할 오류가 발생합니다.
예:
씨
// C program to demonstrate segmentation> // fault when value is passed to scanf> #include> int> main()> {> >int> n = 2;> >scanf>(>'%d'>, n);> >return> 0;> }> |
>
>
C++
문자열을 문자로 변환하는 방법
// C++ program to demonstrate segmentation> // fault when value is passed to scanf> #include> using> namespace> std;> int> main()> {> >int> n = 2;> >cin>> n;> >return> 0;> }> |
>
>
산출
Segementation Fault>
5. 스택 오버플로
코드에 단일 포인터가 없더라도 포인터 관련 문제는 아닙니다. 스택의 메모리가 부족하기 때문입니다. 이는 또한 큰 배열 크기, 많은 수의 재귀 호출, 많은 지역 변수 등으로 인해 발생할 수 있는 메모리 손상 유형이기도 합니다.
예:
씨
// C program to illustrate the> // segmentation fault due to> // stack overflow> #include> int> main()> {> >int> arr[2000000000];> >return> 0;> }> |
>
>
C++
// C++ program to illustrate> // the segmentation fault> // due to stack overflow> #include> using> namespace> std;> int> main()> {> >int> array[2000000000];> >return> 0;> }> |
>
>
산출
Segmentation Fault>
6. 버퍼 오버플로
버퍼에 저장되는 데이터가 버퍼에 할당된 크기보다 크면 버퍼 오버플로가 발생하여 분할 오류가 발생합니다. C 언어의 대부분의 메소드는 바운드 검사를 수행하지 않으므로 버퍼에 필요한 크기를 할당하는 것을 잊었을 때 버퍼 오버플로가 자주 발생합니다.
예:
씨
// C program to illustrate the> // segementation fault due to> // buffer overflow> #include> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }> |
>
>
C++
// C++ program to illustrate the> // segementation fault due to> // buffer overflow> #include> using> namespace> std;> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }> |
>
>
산출
Segmentation Fault>
7. 초기화되지 않은 포인터 또는 NULL 포인터 역참조
초기화되지 않은 포인터(와일드 포인터)를 역참조하는 것은 일반적인 프로그래밍 오류로, 이로 인해 정의되지 않은 동작이 발생할 수 있습니다. 포인터를 유효한 포인터로 처리하고 해당 기본 값에 액세스하는 컨텍스트에서 포인터가 사용되면 유효한 메모리 위치를 가리키도록 초기화되지 않은 경우에도 이 오류가 발생합니다. 이로 인해 데이터 손상, 프로그램 오류 또는 분할 오류가 발생할 수 있습니다. 역참조할 때의 환경과 상태에 따라 초기화되지 않은 포인터는 다른 결과를 낳을 수 있습니다.
우리가 알고 있듯이 NULL 포인터는 어떤 메모리 위치도 가리키지 않으므로 이를 역참조하면 분할 오류가 발생합니다.
예:
씨
// C program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >printf>(>'%d %d'>, *ptr, *nptr);> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> using> namespace> std;> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >cout << *ptr <<>' '> << *nptr;> >return> 0;> }> |
>
>
산출
Segmentation Fault>
분할 오류를 수정하는 방법?
언급된 원인에 주의하여 분할 오류를 수정할 수 있습니다.
- 문자열 리터럴을 수정하지 마십시오.
- 포인터는 가장 일반적인 원인 중 하나이므로 사용할 때는 주의하세요.
- 버퍼 또는 스택 오버플로를 방지하려면 데이터를 저장하기 전에 버퍼 및 스택 크기를 고려하십시오.
- 배열 요소에 액세스하기 전에 경계를 확인합니다.
- 잘못된 형식 지정자 또는 버퍼 오버플로를 방지하려면 scanf() 및 printf()를 주의해서 사용하십시오.
전반적으로 분할 오류의 원인은 해당 공간에서 자신에게 속하지 않은 메모리에 액세스하는 것입니다. 그렇게 하지 않는 한 분할 오류를 피할 수 있습니다. 그래도 오류의 원인을 찾을 수 없다면 프로그램의 오류 지점으로 직접 연결되는 디버거를 사용하는 것이 좋습니다.