세그먼테이션 결함이란 무엇입니까? C와 C ++에서 다른가요? 분할 오류와 매달려 포인터는 어떻게 관련되어 있습니까?
NullPointerException
.
세그먼테이션 결함이란 무엇입니까? C와 C ++에서 다른가요? 분할 오류와 매달려 포인터는 어떻게 관련되어 있습니까?
NullPointerException
.
답변:
세그먼트 오류는 "귀하가 아닌"메모리에 액세스하여 발생하는 특정 종류의 오류입니다. 메모리를 손상시키고 디버그하기 어려운 메모리 버그를 방지하는 도우미 메커니즘입니다. segfault를 얻을 때마다 메모리에 문제가 있음을 알 수 있습니다. 이미 해제 된 변수에 액세스하고 메모리의 읽기 전용 부분에 쓰는 것 등 메모리 관리에서 C와 C ++의 segfault 사이에는 기본 차이가 없습니다.
적어도 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가 생길 것입니다.
c
은 그것이 로컬 이라는 것을 이해해야합니다 . 그것은 그것이 스택 후에 밀려오고 나서 {
팝 아웃 되었음을 의미합니다 }
. 매달려있는 포인터는 이제 스택에서 벗어난 오프셋에 대한 참조 일뿐입니다. 그래서 간단한 프로그램으로 수정해도 segfault가 발생하지 않습니다. 반면에 더 복잡한 사용 사례에서는 다른 함수 호출로 스택이 커지고 매달려있는 포인터가 가리키는 데이터가 포함될 수있는 segfault가 발생할 수 있습니다. 해당 데이터 (로컬 변수)에 쓰면 정의되지 않은 동작 (segfault & Co)이 발생합니다.
SIGSEGV
하므로 스택과의 맹 글링과 같은 신호가 예상되지 않습니다.
그것은 단순히 불가능하기 때문에 다른 프로세스 메모리에 직접 액세스하여 세그먼트 화 결함이 발생하지 않는다는 점에 주목할 가치가 있습니다. 가상 메모리를 사용하면 모든 프로세스에 고유 한 가상 주소 공간이 있으며 포인터 값을 사용하여 다른 프로세스에 액세스 할 수 없습니다. 예외는 다른 가상 주소에 매핑 된 동일한 물리적 주소 공간과 모든 프로세스에서 동일한 방식으로 매핑 된 커널 메모리 인 공유 라이브러리 일 수 있습니다 (syscall에서 TLB 플러시를 피하기 위해 생각합니다). 그리고 shmat;)와 같은 것들-이것이 '간접적 인'접근으로 계산됩니다. 그러나 프로세스 코드에서 먼 거리에 있고 일반적으로 액세스 할 수 있는지 확인할 수 있습니다.
그럼에도 불구하고 (프로세스) 메모리에 부적절한 방식으로 액세스하는 경우 (예 : 쓰기 불가능한 공간에 쓰려고하는 경우) 세그먼테이션 오류가 발생할 수 있습니다. 그러나 가장 일반적인 이유는 실제 주소 공간에 전혀 맵핑되지 않은 가상 주소 공간의 일부에 대한 액세스 입니다.
그리고 가상 메모리 시스템과 관련하여이 모든 것이 가능합니다.
세그먼테이션 결함은 프로세스가 디스크립터 테이블에 나열되지 않은 페이지 요청 또는 프로세스가 나열한 페이지에 대한 유효하지 않은 요청 (예 : 읽기 전용 페이지의 쓰기 요청)으로 인해 발생합니다.
매달려있는 포인터는 유효한 페이지를 가리 키거나 가리지 않지만 "예기치 않은"메모리 세그먼트를 가리키는 포인터입니다.
솔직히 말하면, 다른 포스터에서 언급했듯이 Wikipedia에는 이것에 대한 훌륭한 기사 가 있으므로 살펴보십시오. 이 유형의 오류는 매우 흔하며 종종 액세스 위반 또는 일반 보호 오류와 같은 다른 것입니다.
C, C ++ 또는 포인터를 허용하는 다른 언어에서는 다르지 않습니다. 이러한 종류의 오류는 일반적으로 다음과 같은 포인터로 인해 발생합니다.
분할 오류 는 하드웨어 오류 (이 경우 RAM 메모리)로 인해 발생합니다. 이것은 덜 일반적인 원인이지만 코드에서 오류를 찾지 못하면 memtest가 도움이 될 수 있습니다.
이 경우 솔루션은 RAM을 변경하십시오.
편집하다:
여기에 참조가 있습니다 : 하드웨어에 의한 분할 오류
프로세스 (프로그램 인스턴스 실행)가 다른 프로세스에서 사용중인 읽기 전용 메모리 주소 또는 메모리 범위에 액세스하거나 존재하지 않는 (유효하지 않은) 메모리 주소에 액세스하려고 할 때 세그먼테이션 결함이 발생합니다. 댕글 링 참조 (포인터) 문제 는 내용이 메모리에서 이미 삭제 된 객체 또는 변수에 액세스하려고 시도하는 것을 의미합니다.
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
Wikipedia의 Segmentation_fault 페이지에는 그 원인과 이유를 지적하는 매우 좋은 설명이 있습니다. 자세한 설명은 위키를 살펴보십시오.
컴퓨팅에서 세그먼테이션 오류 (종종 segfault로 단축 됨) 또는 액세스 위반은 메모리 보호 기능이있는 하드웨어에서 발생하는 결함으로, 운영 체제 (OS)에 메모리 액세스 위반을 알립니다.
다음은 세그먼테이션 오류의 일반적인 원인입니다.
이는 종종 잘못된 메모리 액세스를 초래하는 프로그래밍 오류로 인해 발생합니다.
초기화되지 않은 포인터 (임의의 메모리 주소를 가리키는 와일드 포인터)에 대한 참조 또는 할당
해제 된 포인터 (해제 / 할당 해제 / 삭제 된 메모리를 가리키는 매달려 포인터)에 대한 참조 해제 또는 할당
버퍼 오버 플로우.
스택 오버플로
올바르게 컴파일되지 않은 프로그램을 실행하려고합니다. (컴파일 타임 오류가 존재하더라도 일부 컴파일러는 실행 파일을 출력합니다.)
간단히 말해 : 세그먼테이션 오류는 운영 체제가 프로그램에 잘못된 메모리 액세스를 감지했으며 메모리가 손상되지 않도록 프로그램을 조기 종료한다는 신호를 프로그램에 보내는 것입니다.
프로그램이 존재하지 않는 메모리 위치에 액세스하려고 시도하거나 허용되지 않는 방식으로 메모리 위치에 액세스하려고하면 세그먼트 화 결함 또는 액세스 위반이 발생합니다.
/* "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;
세그먼트 폴트가 발생되도록 여기에 [1000]이 존재하지.
세그먼테이션 결함의 원인 :
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).
세그먼트 오류의 충분한 정의가있다, 나는 어리석은 실수를 보일 수 있지만 많은 시간을 낭비 프로그래밍시, 건너 온 몇 가지 예를 인용하고 싶습니다.
printf에서 argumet 유형이 일치하지 않으면 아래의 경우 세그먼테이션 오류가 발생할 수 있습니다.
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
출력 : Segmentation Fault (SIGSEGV)
포인터에 메모리를 할당하는 것을 잊었지만 사용하려고 할 때.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
출력 : Segmentation Fault (SIGSEGV)
단순한 의미 Segmentation fault
는 귀하가 소유하지 않은 일부 메모리에 액세스하려고한다는 것입니다. Segmentation fault
읽기 전용 메모리 위치에서 작업을 읽거나 쓰려고 시도하거나 메모리를 비우려고 할 때 발생합니다. 다시 말해, 이것을 일종의 메모리 손상으로 설명 할 수 있습니다.
아래에서는 프로그래머가 저지른 일반적인 실수에 대해 언급합니다 Segmentation fault
.
scanf()
잘못된 방법으로 사용하십시오 (넣는 것을 잊었습니다 &
).int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
및 scanf()
'을 사용할 때 잘못된 형식 지정자를 사용하십시오.