Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 15: 예외 처리와 디버깅Topic 1: 예외 처리 기본

Topic 1: 예외 처리 기본 🚨

🎯 학습 목표

  • 예외 처리의 필요성과 개념을 이해할 수 있다
  • try-catch-throw 문법을 활용하여 예외를 처리할 수 있다
  • 표준 예외 클래스들의 종류와 특징을 파악할 수 있다
  • 게임 프로그래밍에서 발생하는 실제 오류를 예외 처리로 해결할 수 있다
  • 안전한 프로그램 작성을 위한 예외 처리 패턴을 적용할 수 있다

🛡️ 안전망으로서의 예외 처리

프로그램에서 예상치 못한 오류는 언제든 발생할 수 있어요! 💥

서커스 곡예사의 안전망 비유:

  • 정상 실행 = 곡예사의 공연 🎪

    • 계획된 대로 멋지게 진행
    • 모든 것이 완벽할 때
  • 예외 상황 = 곡예사가 떨어짐 😱

    • 예상치 못한 실수나 문제
    • 프로그램이 갑자기 멈춤
  • 예외 처리 = 안전망 🛡️

    • 떨어져도 안전하게 받아줌
    • 프로그램이 비정상 종료되지 않고 복구
// 예외 처리 없는 경우 (위험!) int result = 10 / 0; // 💥 프로그램 크래시! // 예외 처리가 있는 경우 (안전!) try { int result = 10 / 0; } catch (...) { cout << "🛡️ 안전망이 작동했습니다!" << endl; }

🚨 예외 처리의 3요소

C++에서 예외 처리는 3가지 키워드로 구성됩니다:

1. try - 위험 구간 설정 ⚠️

try { // 예외가 발생할 수 있는 코드 // "이 부분에서 문제가 생길 수 있어요!" }

2. catch - 예외 포착 🎣

catch (예외타입 e) { // 예외가 발생했을 때 실행할 코드 // "문제가 생기면 이렇게 해결하겠습니다!" }

3. throw - 예외 던지기 💣

throw 예외객체; // "문제가 발생했음을 알립니다!"

🎮 첫 번째 예외 처리 예제

게임 캐릭터 레벨업 시스템

#include <iostream> #include <stdexcept> // 표준 예외 클래스 using namespace std; class GameCharacter { private: string name; int level; int exp; public: GameCharacter(string n) : name(n), level(1), exp(0) {} void gainExp(int amount) { if (amount < 0) { // 음수 경험치는 허용하지 않음 throw invalid_argument("경험치는 음수가 될 수 없습니다!"); } exp += amount; cout << name << "이(가) " << amount << " 경험치를 획득했습니다! ✨" << endl; // 레벨업 체크 if (exp >= 100) { levelUp(); } } void levelUp() { if (level >= 100) { throw runtime_error("최대 레벨에 도달했습니다!"); } level++; exp = 0; cout << "🎉 " << name << "이(가) 레벨 " << level << "로 레벨업했습니다!" << endl; } void showStatus() { cout << "🎮 캐릭터: " << name << " | 레벨: " << level << " | 경험치: " << exp << "/100" << endl; } }; int main() { cout << "🎮 RPG 게임 시스템 🎮" << endl; cout << "=====================" << endl; GameCharacter hero("용감한전사"); hero.showStatus(); cout << endl; // 정상적인 경험치 획득 try { cout << "📈 경험치 획득 테스트:" << endl; hero.gainExp(30); hero.gainExp(25); hero.gainExp(50); // 레벨업 발생 hero.showStatus(); cout << endl; } catch (const invalid_argument& e) { cout << "❌ 입력 오류: " << e.what() << endl; } catch (const runtime_error& e) { cout << "⚠️ 실행 오류: " << e.what() << endl; } // 예외 상황 1: 음수 경험치 try { cout << "🚨 음수 경험치 테스트:" << endl; hero.gainExp(-10); // 예외 발생! } catch (const invalid_argument& e) { cout << "❌ 잘못된 입력: " << e.what() << endl; cout << "✅ 시스템이 안전하게 처리했습니다!" << endl; } cout << endl; // 예외 상황 2: 최대 레벨 도달 try { cout << "🚨 최대 레벨 테스트:" << endl; // 강제로 레벨 99로 설정 후 레벨업 시도 for (int i = 0; i < 98; i++) { hero.gainExp(100); // 강제 레벨업 } hero.gainExp(100); // 레벨 100 도달, 예외 발생! } catch (const runtime_error& e) { cout << "⚠️ " << e.what() << endl; cout << "✅ 최대 레벨 제한이 올바르게 작동합니다!" << endl; } hero.showStatus(); return 0; }

📚 표준 예외 클래스들

C++에서 제공하는 주요 예외 클래스들:

1. logic_error 계열 🧠

#include <stdexcept> // 논리적 오류 (프로그래밍 실수) try { throw invalid_argument("잘못된 매개변수!"); throw out_of_range("배열 범위 초과!"); throw length_error("길이 오류!"); } catch (const logic_error& e) { cout << "논리 오류: " << e.what() << endl; }

2. runtime_error 계열 ⚡

// 실행 시간 오류 (예측 불가능한 상황) try { throw runtime_error("실행 시간 오류!"); throw overflow_error("오버플로우 발생!"); throw underflow_error("언더플로우 발생!"); } catch (const runtime_error& e) { cout << "실행 오류: " << e.what() << endl; }

3. 시스템 예외들 🖥️

try { throw bad_alloc(); // 메모리 할당 실패 } catch (const bad_alloc& e) { cout << "메모리 부족: " << e.what() << endl; }

🎯 실전 예제: 게임 리소스 관리 시스템

파일 로딩과 메모리 할당 예외 처리

#include <iostream> #include <fstream> #include <stdexcept> #include <vector> using namespace std; class GameResourceManager { private: vector<string> loadedTextures; vector<int*> allocatedMemory; public: ~GameResourceManager() { // 소멸자에서 메모리 정리 for (int* ptr : allocatedMemory) { delete[] ptr; } } // 텍스처 파일 로딩 void loadTexture(const string& filename) { if (filename.empty()) { throw invalid_argument("파일명이 비어있습니다!"); } ifstream file(filename); if (!file.is_open()) { throw runtime_error("파일을 열 수 없습니다: " + filename); } loadedTextures.push_back(filename); cout << "✅ " << filename << " 텍스처 로딩 완료! 🖼️" << endl; file.close(); } // 메모리 할당 void allocateGameMemory(int size) { if (size <= 0) { throw invalid_argument("메모리 크기는 양수여야 합니다!"); } if (size > 1000000) { // 1MB 제한 throw length_error("너무 큰 메모리 요청입니다!"); } try { int* memory = new int[size]; allocatedMemory.push_back(memory); cout << "✅ " << size << "개 정수 메모리 할당 완료! 💾" << endl; } catch (const bad_alloc& e) { throw runtime_error("메모리 할당에 실패했습니다!"); } } // 게임 데이터 유효성 검사 void validatePlayerData(int level, int hp, int mp) { if (level < 1 || level > 100) { throw out_of_range("레벨은 1~100 사이여야 합니다!"); } if (hp < 0) { throw invalid_argument("HP는 음수가 될 수 없습니다!"); } if (mp < 0) { throw invalid_argument("MP는 음수가 될 수 없습니다!"); } cout << "✅ 플레이어 데이터 검증 완료! 👤" << endl; } void showStatus() { cout << "📊 리소스 상태:" << endl; cout << " 로딩된 텍스처: " << loadedTextures.size() << "개" << endl; cout << " 할당된 메모리: " << allocatedMemory.size() << "블록" << endl; } }; int main() { cout << "🎮 게임 리소스 관리 시스템 🎮" << endl; cout << "================================" << endl; GameResourceManager resourceMgr; // 1. 텍스처 로딩 테스트 cout << "🖼️ 텍스처 로딩 테스트:" << endl; try { resourceMgr.loadTexture("hero.png"); resourceMgr.loadTexture("background.jpg"); resourceMgr.loadTexture(""); // 예외 발생! } catch (const invalid_argument& e) { cout << "❌ 입력 오류: " << e.what() << endl; } catch (const runtime_error& e) { cout << "❌ 실행 오류: " << e.what() << endl; } cout << endl; // 2. 메모리 할당 테스트 cout << "💾 메모리 할당 테스트:" << endl; try { resourceMgr.allocateGameMemory(1000); resourceMgr.allocateGameMemory(5000); resourceMgr.allocateGameMemory(-100); // 예외 발생! } catch (const invalid_argument& e) { cout << "❌ 입력 오류: " << e.what() << endl; } catch (const length_error& e) { cout << "❌ 크기 오류: " << e.what() << endl; } catch (const runtime_error& e) { cout << "❌ 실행 오류: " << e.what() << endl; } cout << endl; // 3. 플레이어 데이터 검증 테스트 cout << "👤 플레이어 데이터 검증 테스트:" << endl; try { resourceMgr.validatePlayerData(25, 150, 80); // 정상 resourceMgr.validatePlayerData(101, 100, 50); // 레벨 초과! } catch (const out_of_range& e) { cout << "❌ 범위 오류: " << e.what() << endl; } catch (const invalid_argument& e) { cout << "❌ 입력 오류: " << e.what() << endl; } cout << endl; // 4. 여러 예외를 한번에 처리 cout << "🎲 종합 테스트 (여러 예외 처리):" << endl; try { resourceMgr.validatePlayerData(50, -10, 30); // HP 음수! resourceMgr.allocateGameMemory(2000000); // 메모리 초과! } catch (const exception& e) { // 모든 표준 예외의 기본 클래스 cout << "❌ 예외 발생: " << e.what() << endl; cout << "✅ 안전하게 처리되었습니다!" << endl; } cout << endl; resourceMgr.showStatus(); cout << "🛡️ 모든 예외가 안전하게 처리되었습니다!" << endl; return 0; }

🔄 예외 전파와 다중 catch

예외 처리의 흐름 이해

#include <iostream> #include <stdexcept> using namespace std; // 함수들이 연쇄적으로 예외를 전파 void level3Function() { cout << "🔍 Level 3: 깊은 곳에서 문제 발견!" << endl; throw runtime_error("Level 3에서 오류 발생!"); } void level2Function() { cout << "⚡ Level 2: 처리 중..." << endl; level3Function(); // 예외가 여기로 전파됨 } void level1Function() { cout << "🚀 Level 1: 시작..." << endl; level2Function(); // 예외가 여기로 전파됨 } int main() { cout << "🎯 예외 전파 테스트" << endl; cout << "==================" << endl; try { level1Function(); } catch (const runtime_error& e) { cout << "🛡️ Main에서 예외 포착: " << e.what() << endl; } cout << "✅ 프로그램이 정상적으로 계속 실행됩니다!" << endl; return 0; }

🚨 예외 처리 모범 사례

1. 구체적인 예외부터 처리 📌

try { // 위험한 코드 } catch (const out_of_range& e) { // 구체적 cout << "범위 오류: " << e.what() << endl; } catch (const logic_error& e) { // 일반적 cout << "논리 오류: " << e.what() << endl; } catch (const exception& e) { // 가장 일반적 cout << "기타 오류: " << e.what() << endl; }

2. RAII 원칙 준수 🔄

class GameResource { public: GameResource() { cout << "리소스 생성 🔧" << endl; } ~GameResource() { cout << "리소스 정리 🧹" << endl; } }; void safeFunction() { GameResource resource; // 자동으로 정리됨 throw runtime_error("오류 발생!"); // 예외가 발생해도 안전 }

💡 핵심 정리

  • 예외 처리: 프로그램의 예상치 못한 오류를 안전하게 처리하는 메커니즘
  • try-catch-throw: 예외 처리의 3요소로 안전한 프로그램 작성
  • 표준 예외: logic_error(논리 오류), runtime_error(실행 오류) 계열 활용
  • 예외 전파: 함수 호출 체인을 따라 예외가 상위로 전달
  • 구체적 처리: 구체적인 예외부터 일반적인 예외 순으로 catch 블록 배치
  • RAII 원칙: 예외 발생 시에도 자원이 안전하게 정리되도록 설계

✅ 실습 체크리스트

🚀 다음 시간 예고

다음 시간에는 사용자 정의 예외에 대해 알아볼 거예요!

  • 나만의 예외 클래스 만들기
  • 게임별 특화된 예외 처리 시스템
  • 예외 클래스 계층 구조 설계
  • 맞춤형 오류 메시지와 복구 전략

“예외 처리로 더 안전하고 견고한 프로그램을 만들어보세요! 🛡️✨”

Last updated on