Programing

세그먼테이션 결함이란 무엇입니까?

lottogame 2020. 2. 11. 22:19
반응형

세그먼테이션 결함이란 무엇입니까?


세그먼테이션 결함이란 무엇입니까? C와 C ++에서 다른가요? 분할 오류와 매달려 포인터는 어떤 관련이 있습니까?


세그먼트 오류는 "귀하가 아닌"메모리에 액세스 할 때 발생하는 특정 종류의 오류입니다. 메모리를 손상시키지 않고 디버그하기 어려운 메모리 버그를 방지하는 도우미 메커니즘입니다. segfault를 얻을 때마다 메모리에 문제가 있음을 알 수 있습니다. 이미 해제 된 변수에 액세스하거나 메모리의 읽기 전용 부분에 쓰는 것 등. 세그멘테이션 오류는 대부분의 언어에서 기본적으로 동일합니다. 메모리 관리에서 C와 C ++의 segfaults는 기본적으로 차이가 없습니다.

적어도 C (++)와 같은 저수준 언어에서 segfault를 얻는 방법에는 여러 가지가 있습니다. segfault를 얻는 일반적인 방법은 null 포인터를 역 참조하는 것입니다.

int *p = NULL;
*p = 1;

읽기 전용으로 표시된 메모리 부분에 쓰려고 할 때 또 다른 segfault가 발생합니다.

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

매달려있는 포인터는 더 이상 존재하지 않는 것을 가리 킵니다.

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

포인터 가 블록이 끝난 후에 존재하지 않는 p문자 변수 c가리 키기 때문에 매달려 있습니다. 그리고 매달려있는 포인터 (와 같은 *p='A') 를 역 참조하려고 하면 segfault가 생길 것입니다.


그것은 단순히 불가능하기 때문에 다른 프로세스 메모리 (이것은 내가 듣고있는 것입니다)에 직접 액세스하여 세그먼트 오류가 발생하지 않는다는 점에 주목할 가치가 있습니다. 가상 메모리를 사용하면 모든 프로세스에 고유 한 가상 주소 공간이 있으며 포인터 값을 사용하여 다른 프로세스에 액세스 할 수 없습니다. 예외는 다른 가상 주소에 매핑 된 동일한 물리적 주소 공간과 모든 프로세스에서 동일한 방식으로 매핑되는 커널 메모리 인 공유 라이브러리 일 수 있습니다 (syscall에서 TLB 플러시를 피하기 위해 생각합니다). 그리고 shmat;)와 같은 것들-이것이 '간접적 인'접근으로 계산됩니다. 그러나 프로세스 코드에서 먼 거리에 있고 일반적으로 액세스 할 수 있는지 확인할 수 있습니다.

그럼에도 불구하고 (프로세스) 메모리에 부적절한 방식으로 액세스하는 경우 (예 : 쓰기 불가능한 공간에 쓰려고하는 경우) 세그먼트 오류가 발생할 수 있습니다. 그러나 가장 일반적인 이유는 실제 주소 공간에 전혀 맵핑되지 않은 가상 주소 공간의 일부에 대한 액세스 입니다.

가상 메모리 시스템과 관련하여이 모든 것이 가능합니다.


세그먼트 화 결함은 프로세스가 디스크립터 테이블에 나열되지 않은 페이지 요청 또는 프로세스가 나열한 페이지에 대한 유효하지 않은 요청 (예 : 읽기 전용 페이지의 쓰기 요청)으로 인해 발생합니다.

매달려있는 포인터는 유효한 페이지를 가리 키거나 가리지 않지만 "예기치 않은"메모리 세그먼트를 가리키는 포인터입니다.


솔직히 말하면, 다른 포스터에서 언급했듯이 Wikipedia에는 ​​이것에 대한 훌륭한 기사 가 있으므로 살펴보십시오. 이 유형의 오류는 매우 흔하며 종종 액세스 위반 또는 일반 보호 오류와 같은 다른 것입니다.

C, C ++ 또는 포인터를 허용하는 다른 언어에서는 다르지 않습니다. 이러한 종류의 오류는 일반적으로 다음과 같은 포인터로 인해 발생합니다.

  1. 제대로 초기화되기 전에 사용
  2. 그들이 가리키는 메모리가 재 할당되거나 삭제 된 후에 사용됩니다.
  3. 인덱스가 배열 범위를 벗어난 인덱스 배열에 사용됩니다. 이것은 일반적으로 STL / Boost 기반 컬렉션 (C ++)이 아닌 기존 배열 또는 c 문자열에서 포인터 수학을 수행 할 때만 발생합니다.

Wikipedia에 따르면 :

프로그램이 액세스 할 수없는 메모리 위치에 액세스하려고 시도하거나 허용되지 않는 방식으로 메모리 위치에 액세스하려고하면 (예 : 읽기 전용 위치에 쓰려고 시도하거나) 운영 체제의 일부를 덮어 씁니다.


분할 오류 는 하드웨어 오류 (이 경우 RAM 메모리)로 인해 발생합니다. 이것은 덜 일반적인 원인이지만 코드에서 오류를 찾지 못하면 memtest가 도움이 될 수 있습니다.

이 경우 솔루션은 RAM을 변경하십시오.

편집하다:

여기에 참조가 있습니다 : 하드웨어에 의한 분할 오류


프로세스 (프로그램 인스턴스 실행)가 다른 프로세스에서 사용중인 읽기 전용 메모리 주소 또는 메모리 범위에 액세스하거나 존재하지 않는 (유효하지 않은) 메모리 주소에 액세스하려고 할 때 세그먼테이션 결함이 발생합니다. 댕글 링 참조 (포인터) 문제 는 내용이 메모리에서 이미 삭제 된 객체 또는 변수에 액세스하려고 시도하는 것을 의미합니다.

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here

Wikipedia의 Segmentation_fault 페이지에는 그 원인과 이유를 지적하는 매우 좋은 설명이 있습니다. 자세한 설명은 위키를 살펴보십시오.

컴퓨팅에서 세그먼테이션 오류 (종종 segfault로 단축 됨) 또는 액세스 위반은 메모리 보호 기능이있는 하드웨어에서 발생하는 결함으로, 운영 체제 (OS)에 메모리 액세스 위반을 알립니다.

다음은 세그먼테이션 오류의 일반적인 원인입니다.

  • NULL 포인터 역 참조 – 메모리 관리 하드웨어에서 특수한 경우
  • 존재하지 않는 메모리 주소 액세스 시도 (외부 프로세스의 주소 공간)
  • 메모리에 액세스하려고 시도하면 프로그램에 대한 권한이 없습니다 (예 : 프로세스 컨텍스트의 커널 구조).
  • 읽기 전용 메모리 (코드 세그먼트 등)를 쓰려고 시도

이는 종종 메모리 액세스가 유효하지 않은 프로그래밍 오류로 인해 발생합니다.

  • 초기화되지 않은 포인터 (임의의 메모리 주소를 가리키는 와일드 포인터)에 대한 참조 또는 할당

  • 해제 된 포인터 (해제 / 할당 해제 / 삭제 된 메모리를 가리키는 매달려 포인터)에 대한 참조 해제 또는 할당

  • 버퍼 오버 플로우.

  • 스택 오버플로

  • 올바르게 컴파일되지 않은 프로그램을 실행하려고합니다. (일부 컴파일러는 컴파일 타임 오류가 있음에도 불구하고 실행 파일을 출력합니다.)


간단히 말해 : 세그먼테이션 오류는 운영 체제가 프로그램에 잘못된 메모리 액세스를 감지했으며 메모리가 손상되지 않도록 프로그램을 조기 종료한다는 신호를 프로그램에 보내는 것입니다.


프로그램이 존재하지 않는 메모리 위치에 액세스하려고 시도하거나 허용되지 않는 방식으로 메모리 위치에 액세스하려고하면 세그먼트 화 결함 또는 액세스 위반이 발생합니다.

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

여기서 i [1000]이 존재하지 않으므로 segfault가 발생합니다.

세그먼테이션 결함의 원인 :

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).

사이의 관계에 참여하는 "핵심 덤프"여기서 답변에서 "분할 오류"여러 좋은의 설명이 있습니다 만, 세그먼트 오류와 이후 종종 메모리 내용의 덤프있어, 내가 공유하기를 원해요 분할 오류 (코어 덤프) 및 메모리는 다음과 같습니다.

약 1955 년부터 1975 년까지-반도체 메모리 이전-컴퓨터 메모리의 지배적 인 기술은 구리선에 작은 자석 도넛을 사용했습니다. 도넛은 "페라이트 코어"로 알려져 있으며 메인 메모리는 "코어 메모리"또는 "코어"로 알려져 있습니다.

여기 에서 찍은 .


"세그먼트 결함"은 액세스 할 수없는 메모리에 액세스하려고 시도했음을 의미합니다.

첫 번째 문제는 main의 주장에 관한 것입니다. main 함수는 int main (int argc, char * argv [])이어야하며 argv [1]에 액세스하기 전에 argc가 2 이상인지 확인해야합니다.

또한 float를 printf로 전달하고 있기 때문에 printf로 전달할 때 double로 변환되므로 % f 형식 지정자를 사용해야합니다. % s 형식 지정자는 문자열 용입니다 ( '\ 0'- 종료 문자 배열).

참고 URL : https://stackoverflow.com/questions/2346806/what-is-a-segmentation-fault



반응형