C++ 프로그램의 비정상적인 동작은 종종 프로그램 크래시(비정상 종료)로 이어집니다. 세그멘테이션 오류(Segmentation Fault), 비정상 종료(Aborted), 부동 소수점 예외(Floating Point Exception)와 같은 문제를 한 번쯤 겪어보셨을 것입니다.
아래 예제 프로그램들은 C++ 프로그램이 크래시되는 대표적인 원인을 이해하는 데 도움이 될 것입니다.
예외(Exceptions)
C++에서 예외(Exception)란 프로그램이 비정상적인 상황에 직면했을 때 나타나는 반응을 의미합니다. try-catch 블록으로 이러한 예외를 적절하게 처리하지 않으면 프로그램이 크래시될 수 있습니다. 아래 프로그램은 0으로 나누는 연산으로 인해 예외가 발생하여 크래시됩니다.
예제
#include <iostream>
int main(){
int num1=10;
int num2=0;
int quotient=num1/num2;
printf("\n Quotient is: %d",quotient);
return 0;
}
출력
Floating point exception (core dumped)
버퍼 오버플로우(Buffer Overflow)
버퍼(Buffer)는 데이터를 임시로 저장하는 공간입니다. 프로그램이 버퍼에 데이터를 기록할 때 버퍼가 수용할 수 있는 크기를 초과하면, 초과된 데이터는 버퍼의 경계를 벗어나 인접한 메모리 영역을 덮어쓰게 됩니다. 아래 프로그램은 입력값이 변수가 담을 수 있는 크기를 초과할 때 비정상적으로 동작합니다.
예제
#include <iostream>
#include <string.h>
int main(){
int num=100;
std::cout<<"\nValue for num:"<<num;
char c[2];
strcpy(c,"abcdefghijklmnopqrstuvwxyz");
std::cout<<"\nValue for c:"<<c;
return 0;
}
출력
Value for num:100 Segmentation fault (core dumped)
스택 오버플로우(Stack Overflow)
스택 오버플로우는 호출 스택 포인터가 스택의 경계를 초과할 때 발생하는 문제입니다. 스택은 제한된 크기의 공간으로 구성되어 있으며, 프로그램이 스택에서 사용 가능한 공간보다 더 많은 공간을 사용하면 스택이 넘쳐흘러 프로그램이 크래시됩니다. 가장 흔한 원인은 무한 재귀 호출입니다.
아래 프로그램에는 factorial() 함수를 무한히 호출하는 코드가 포함되어 있습니다. return 문이 올바르게 작성되지 않았습니다.
예제
#include <iostream>
#include <string.h>
int factorial(int num){
if(num==0)
return 1;
else
return(factorial(num));
}
int main(){
int n=10;
int fact=factorial(n);
std::cout<<fact;
}
출력
Segmentation fault (core dumped)
세그멘테이션 오류(Segmentation Fault)
세그멘테이션 오류 또는 코어 덤프(core dump)는 프로그램이 자신에게 허용되지 않은 메모리 영역에 접근하려고 할 때 발생합니다. 아래 프로그램에서 포인터 str는 계속 증가하면서 메모리에 무한정 값을 덮어씁니다.
예제
#include <iostream>
int main(){
char *str;
char name[]="iostream";
str=name;
while(1)
(*str++)='a';
}
출력
Segmentation fault (core dumped)
메모리 누수(Memory Leaks)
메모리 누수는 동적으로 할당된 메모리가 해제되지 않은 채 방치될 때 발생합니다. 더 이상 사용하지 않는 메모리는 반드시 해제해야 합니다. 메모리를 반복적으로 계속 할당하면 시간이 지남에 따라 누수가 누적되고, 결국 프로그램이 크래시될 수 있습니다. 아래와 같은 잘못된 코드가 반복되면 메모리 누수가 발생합니다.
예제
#include <iostream>
int main(){
int *node;
node = (int *) malloc(9999999);
// free(node);
}
위 예제에서 malloc()으로 할당한 메모리를 free()로 해제하지 않으면 메모리 누수가 발생합니다. 이러한 코드가 반복 실행되면 사용 가능한 메모리가 고갈되어 결국 프로그램이 비정상 종료될 수 있습니다.