programing

초기화되지 않은 포인터에 데이터를 복사/스캔/읽을 때 크래시 또는 "세그멘테이션 장애"가 발생합니다.

yoursource 2022. 7. 16. 00:53
반응형

초기화되지 않은 포인터에 데이터를 복사/스캔/읽을 때 크래시 또는 "세그멘테이션 장애"가 발생합니다.

이 질문은 성격에 관한 모든 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
  1. 포인터는 메모리 위치만 가리킵니다.포인터를 생성했지만 아직 메모리 위치에 바인딩하지 않았습니다. 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");
    
  2. 다음 코드 스니펫을 사용하여 줄바꿈 문자(*)에 도달할 때까지 문자열을 읽을 수 있습니다."%[^\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");

를 사용하는 경우*ptrover에 할당되어 있는 메모리의 할당을 해제하는 것을 잊지 말아 주세요.*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

반응형