ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Segmentation Fault부터 메모리 누수까지, C 언어 에러 완벽 해결법
    에러와 함꼐하는 인생 2025. 1. 17. 13:02

     

    C 언어 런타임 에러와 디버깅 방법

    런타임 에러란 무엇인가?

    런타임 에러(Runtime Error)는 프로그램이 컴파일을 성공적으로 마친 뒤, 실행 중에 발생하는 오류를 뜻합니다. 런타임 에러는 컴파일 단계에서는 발견되지 않기 때문에 디버깅이 까다로울 수 있습니다. 이 글에서는 C 언어로 개발할 때 자주 발생하는 런타임 에러와 이를 효과적으로 디버깅하는 방법을 살펴보겠습니다.

    1. Segmentation Fault

    에러 설명: Segmentation Fault는 잘못된 메모리 접근으로 인해 프로그램이 비정상적으로 종료되는 런타임 에러입니다. 포인터를 잘못 사용하거나, 배열의 범위를 벗어난 접근 시 주로 발생합니다.

    발생 원인

    • 초기화되지 않은 포인터에 접근
    • NULL 포인터에 접근
    • 배열의 크기를 초과한 인덱스 접근

    해결 방법

      • 포인터 초기화: 포인터를 사용하기 전에 반드시 초기화합니다.
    
    int *ptr = NULL;
    ptr = (int *)malloc(sizeof(int) * 10);
    if (ptr != NULL) {
        // 사용 후 메모리 해제
        free(ptr);
        ptr = NULL;
    }
                
      • 배열 범위 확인: 배열 접근 시 범위를 초과하지 않도록 루프 조건을 정확히 설정합니다.
    
    int arr[5];
    for (int i = 0; i < 5; i++) {
        arr[i] = i; // 올바른 배열 접근
    }
                
      • 디버거 활용: gdb를 사용하여 에러 발생 지점을 추적합니다.
    
    gdb ./program
    run
    bt  // 백트레이스를 통해 오류 위치 확인
                

    2. 메모리 누수 (Memory Leak)

    에러 설명: 메모리 누수는 동적으로 할당된 메모리를 해제하지 않아 발생하는 문제로, 프로그램의 메모리 사용량이 지속적으로 증가하는 원인이 됩니다. 메모리 누수는 장시간 실행되는 프로그램에서 특히 심각한 문제를 초래합니다.

    발생 원인

    • malloc() 또는 calloc()로 할당한 메모리를 해제하지 않음
    • 해제된 메모리를 다시 참조하여 Undefined Behavior 발생

    해결 방법

      • 모든 동적 할당 해제: free()를 사용해 메모리를 해제하고, 포인터를 NULL로 초기화합니다.
    
    int *ptr = (int *)malloc(sizeof(int) * 5);
    if (ptr != NULL) {
        // 작업 수행
        free(ptr); // 메모리 해제
        ptr = NULL; // Dangling pointer 방지
    }
                
      • 메모리 누수 검사: valgrind를 사용해 누수를 탐지합니다.
    
    valgrind --leak-check=full ./program
                

    3. 버퍼 오버플로우

    에러 설명: 버퍼 오버플로우(Buffer Overflow)는 데이터가 배열 또는 버퍼의 크기를 초과하여 기록될 때 발생하는 에러입니다. 이는 메모리 손상, 비정상 종료, 심지어 보안 취약점을 야기할 수 있습니다.

    발생 원인

    • 배열 또는 버퍼의 크기를 초과한 데이터 쓰기
    • gets()와 같은 안전하지 않은 함수 사용

    해결 방법

      • 안전한 함수 사용: 문자열 입력 시 fgets()를 사용합니다.
    
    char buffer[10];
    printf("Enter a string: ");
    fgets(buffer, sizeof(buffer), stdin);
                
      • 배열 크기 확인: 배열 복사 시 크기를 초과하지 않도록 주의합니다.
    
    char src[10] = "hello";
    char dest[10];
    strncpy(dest, src, sizeof(dest) - 1);
    dest[sizeof(dest) - 1] = '\0'; // Null-terminate
                

    결론

    런타임 에러는 C 언어 개발 과정에서 흔히 발생하지만, 적절한 디버깅과 예방 방법을 통해 충분히 해결할 수 있습니다. gdbvalgrind와 같은 도구를 적극적으로 활용하고, 메모리 관리에 신중을 기한다면 안정적인 프로그램을 작성할 수 있을 것입니다. 에러를 마주했을 때는 이를 배움의 기회로 삼아 문제 해결 능력을 키워보세요!

Designed by Tistory.