초기화되지 않은 포인터에 데이터를 복사/스캔/읽을 때 크래시 또는 "세그멘테이션 장애"가 발생합니다.
이 질문은 성격에 관한 모든 FAQ에 대한 참조로 사용됩니다.
초기화되지 않은 포인터가 가리키는 주소로 데이터를 복사/스캔하면 알 수 없는 크래시 또는 "세그멘테이션 장애"가 발생하는 이유는 무엇입니까?
예를 들어 다음과 같습니다.
char* ptr;
strcpy(ptr, "hello world"); // crash here!
또는
char* ptr;
scanf("%s", ptr); // crash here!
포인터는 다른 변수의 주소만 포함할 수 있는 특수한 유형의 변수입니다.데이터를 포함할 수 없습니다."데이터를 포인터에 복사/저장"할 수 없습니다. 이는 의미가 없습니다.포인터는 다른 곳에 할당된 데이터를 가리키도록만 설정할 수 있습니다.
즉, 포인터가 의미를 가지려면 항상 유효한 메모리 위치를 가리켜야 합니다.예를 들어 스택에 할당된 메모리를 가리킬 수 있습니다.
{
int data = 0;
int* ptr = &data;
...
}
또는 힙에 동적으로 할당된 메모리:
int* ptr = malloc(sizeof(int));
초기화 전에 포인터를 사용하는 것은 항상 버그입니다.아직 유효한 메모리를 가리키고 있지 않다.
다음 예에서는 모두 프로그램크래시 또는 "세그멘테이션 장애"와 같은 예기치 않은 동작을 일으킬 수 있습니다.
/*** examples of incorrect use of pointers ***/
// 1.
int* bad;
*bad = 42;
// 2.
char* bad;
strcpy(bad, "hello");
대신 포인터가 할당된 메모리를 충분히 가리키도록 해야 합니다.
/*** examples of correct use of pointers ***/
// 1.
int var;
int* good = &var;
*good = 42;
// 2.
char* good = malloc(5 + 1); // allocates memory for 5 characters *and* the null terminator
strcpy(good, "hello");
를 . 이는 "nowhere"를 합니다.NULL
이것에 의해, 유효한 메모리를 가리키지 않는 것을 보증하는, 늘 포인터가 됩니다.이는 포인터를 완전히 초기화하지 않은 상태로 두는 것과는 다릅니다.
int* p1 = NULL; // pointer to nowhere
int* p2; // uninitialized pointer, pointer to "anywhere", cannot be used yet
그러나 늘 포인터로 가리킨 메모리에 액세스하려고 하면 초기화되지 않은 포인터를 사용할 때와 같은 문제가 발생할 수 있습니다.즉, 크래시 또는 세그멘테이션 장애입니다.최선의 경우, 시스템은 사용자가 null 주소에 액세스하려고 하는 것을 인식하고 "null 포인터 예외"를 발생시킵니다.
늘 포인터 예외 버그에 대한 해결책은 동일합니다.사용하기 전에 유효한 메모리를 가리키도록 포인터를 설정해야 합니다.
추가 정보:
잘못된 데이터를 가리키는 포인터
포인터를 사용하여 다른 함수에서 로컬 변수에 액세스하는 방법
로컬 변수의 메모리를 해당 범위 밖에서 액세스할 수 있습니까?
분할 장애 및 원인
세그멘테이션 장애란 무엇입니까?
"char s[]"가 아닌 "char *s"로 초기화된 문자열에 쓸 때 세그멘테이션 장애가 발생하는 이유는 무엇입니까?
chars [ ]와 char *의 차이점은 무엇입니까?
세그멘테이션 장애의 일반적인 이유의 최종 목록
버스 오류란 무엇입니까?
학습 중 C가 작은 따옴표를 사용하여 문자열 리터럴을 나타내려고 할 때 자주 발생하는 상황 중 하나는 다음과 같습니다.
char ptr[5];
strcpy(ptr, 'hello'); // crash here!
// ^ ^ because of ' instead of "
주식회사,'h'
는 1글자의 리터럴입니다만,"h"
스트링 리터럴로,'h'
및 Null 터미네이터\0
(즉, 2글자 배열).또한 C에서 문자 리터럴의 유형은int
,그것은,sizeof('h')
와 동등하다sizeof(int)
,하는 동안에sizeof(char)
이1
.
char h = 'h';
printf("Size: %zu\n", sizeof(h)); // Size: 1
printf("Size: %zu\n", sizeof('h')); // likely output: Size: 4
포인터는 메모리 위치만 가리킵니다.포인터를 생성했지만 아직 메모리 위치에 바인딩하지 않았습니다.
strcpy
는 다음 시그니처와 같은2개의 문자 배열을 가리키는2개의 포인터(첫 번째 포인터는 일정하지 않아야 합니다)를 전달합니다.char * strcpy ( char * destination, const char * source );
사용 예:
char* ptr = malloc(32); strcpy(ptr, "hello world");
char str[32]; strcpy(str, "hello world");
다음 코드 스니펫을 사용하여 줄바꿈 문자(*)에 도달할 때까지 문자열을 읽을 수 있습니다.
"%[^\t\n]s"
(탭, 줄 바꿈) 또는"%[^ \t\n]s"
(스페이스, 탭, 줄 바꿈).char *ptr = malloc(32); scanf("%31[^\n]", ptr);
(실제에서는 다음 값에서 반환되는 값을 확인하는 것을 잊지 마십시오.
scanf()
!)
이 문제는 포인터에 메모리를 할당하지 않았기 때문에 발생합니다. char* ptr
이 경우 포인터에 메모리를 동적으로 할당해야 합니다.
두 가지 기능malloc()
그리고.calloc()
에 사용할 수 있다dynamic memory allocation
.
다음 코드를 시험해 보세요:-
char* ptr;
ptr = malloc(50); // allocate space for 50 characters.
strcpy(ptr, "hello world");
를 사용하는 경우*ptr
over에 할당되어 있는 메모리의 할당을 해제하는 것을 잊지 말아 주세요.*ptr
이 조작은, 다음의 방법으로 실시할 수 있습니다.free()
기능.
free(ptr); // deallocating memory.
동적으로 할당된 메모리의 크기는 다음을 사용하여 변경할 수 있습니다.realloc()
.
char *tmp = realloc(ptr, 100); // allocate space for 100 characters.
if (! tmp) {
// reallocation failed, ptr not freed
perror("Resize failed");
exit(1);
}
else {
// reallocation succeeded, old ptr freed
ptr = tmp;
}
대부분의 경우 "세그먼트 장애"는 메모리 할당 오류 또는 범위를 벗어난 어레이로 인해 발생합니다.
를 사용하는 대신 문자열을 수정할 수 있는 복사본을 만듭니다.malloc
,strlen
그리고.strcpy
, POSIX C 라이브러리는 라고 불리는 편리한 기능을 가지고 있습니다.strdup
에<string.h>
전달된 늘 종단 문자열의 복사본을 할당된 저장 기간과 함께 반환합니다.사용 후에는 포인터를free
:
char* ptr;
ptr = strdup("hello world");
ptr[0] = 'H';
puts(ptr);
free(ptr);
언급URL : https://stackoverflow.com/questions/37549594/crash-or-segmentation-fault-when-data-is-copied-scanned-read-to-an-uninitializ
'programing' 카테고리의 다른 글
vue / composition api를 사용하여 parent에서 하위 구성 요소 메서드를 호출합니다. (0) | 2022.07.17 |
---|---|
스레드 세이프와 재진입 (0) | 2022.07.16 |
봄에 프로그래밍 방식으로 현재 활성/기본 환경 프로파일을 얻으려면 어떻게 해야 합니까? (0) | 2022.07.16 |
Java에서 다른 클래스의 개인 필드 값을 읽는 방법은 무엇입니까? (0) | 2022.07.16 |
vue의 vue-good-table에 편집 버튼을 추가하는 방법 (0) | 2022.07.16 |