• std::exception 의 파생 클래스
    • logic_error
      • invalid_argument
        • 부적절한 argument value | std::bitset::bitset, std::stoi, std::stof
      • domain_error
        • 루트안에 음수를 넣었다거나 하는, 논리상의 도메인을 벗어난 에러, 스탠다드 라이브러리는 이 에러를 출력하지 않음, math_errhandling 같은 자체 에러가 있음. 그러나 boost.math 같은 써드파티 라이브러리에서는 이 에러를 출력함 | boost.math
      • length_error
        • 객체의 한계를 벗어난 시도를 했을때 일어남 | std::basic_string, std::vector::reserve
      • out_of_range
        • 정의된 범위에서 벗어난 원소에 접근하는 시도를 했을때 일어남 | std::bitset, std::basic_string(by std::stoi, std::stod), std::vector::at, std::map::at
      • future_error
        • 스레드 라이브러리에서 출력하는 예외 | std::future, std::promise
    • runtime_error
      • range_error
        • 연산 결과가 destination type으로 변환될 수 없을 때 |  std::wstring_convert::from_bytese, std::wstring_convert::to_bytes
      • overflow_error
        • 연산 결과가 destination type의 크기를 벗어날 때 | std::bitset::to_ulong. std::bitset::to_ullong
      • underflow_error
        • arithmetic underflow, 연산 결과가 원하지 않는 floating-point value를 포함할때 | boost.math
      • regex_error
        • regex 객체를 위한 에러
      • system_error
        • ios_base::failure
          • 입출력에 실패했을 때
        • filesystem::filesystem_error
          • 파일시스템 라이브러리에 포함된 에러, public memeber function으로 path1 과 path2가 있음
      • tx_exception
        • atomic_cancle 키워드와 Transactional memory와 관련이 있음
      • nonexistent_local_time
        • std::chrono 와 관련된 변환 에러
      • abiguous_local_time
        • std::chrono 와 관련된 변환 에러
      • format_error
    • bad_optional_access
      • std::optional::value에서 출력, optioanl object가 값을 가지고 있지 않을때 출력 | std::optional::value
    • bad_typeid
    • bad_cast
      • bad_any_cast
    • bad_weak_ptr
    • bad_function_call
    • bad_alloc
      • bad_array_new_length
    • bad_exception
    • ios_base::failure
    • bad_variant_access

 

  • Example.1 함수 호출은 Stack 이다.
// Example.1 LIFO
#include <iostream>
using namespace std;

class Object {
	static int count;
	int ID;
public:
	Object() { 
		ID = count++;
		cout << "Oject(" << ID << ") created." << endl; 
	}
	~Object() { cout << "Object(" << ID << ") perished" << endl; }
};

int Object::count = 1;

auto main() ->int {
	Object ob1;
	{
		Object ob2;
	}
	Object ob3;
}

/*
Oject(1) created.
Oject(2) created.
Object(2) perished
Oject(3) created.
Object(3) perished
Object(1) perished
*/

 

  • Example.2 일단 한번 에러가 던져지면, try문을 빠져나가기 때문에, 다른 에러는 잡을 수 없다.
// Example.2 예외 던지기
#include <iostream>
#include <string>
#include <vector>

class Person {
	std::string firstname;
	std::string lastname;
	int arbitrarynumber;
public:
	Person() : firstname(""), lastname(""), arbitrarynumber(-1) {}
	Person(std::string first, std::string last, int arbitrary) 
		: firstname(first), lastname(lastname), arbitrarynumber(arbitrary) {
		if (arbitrarynumber == 0) {
			throw std::invalid_argument("Cannot be Zero : arbitrary number");
		}
	}
	std::string GetName() const { return firstname + " " + lastname; }
	int GetNum() const { return arbitrarynumber; }
};

auto main() ->int {
	std::vector<int> v;
	v.push_back(1);
	try {
		Person Nakamura("Nakamura", "Shinichiro", 0);
		int j = v.at(99);
	}
	catch (std::out_of_range& e) {
		std::cout << " out of range exception " << e.what();
	}
	catch (std::exception& e) {
		std::cout << e.what();
	}
}

/*
Cannot be Zero : arbitrary number
*/

 

 

 

  • Stack Unwinding : Example.3
    • When an exception is thrown, If in a try, everything local to try block goes out of scope
      • Destructors go off
      • Control goes to the catch
    • If not, everything local to the function goese out of scope
      • control returns to where that function was called from
      • Recurse to "if in a try" above
    • If you get all the way out of main(), the user gets a dialog
      • But it's more interesting when you end up in a catch
    • 어쨋든, try 문도 스코프로 봐야하기 때문에, try문에서 생성된 객체는 스코프를 벗어나기 전에. 소멸자가 호출되어야 한다.
      • (with RAII) 메모리 할당->생성자 호출-> 예외 발생 -> 소멸자 호출 -> 스코프 벗어나기 -> 예외 출력
      • (without RAII)  메모리할당->생성자 호출 -> 예외 발생 -> 스코프 벗어나기 -> 예외출력 (소멸자 호출 안함은 메모리릭을 의미)
 

C++ RAII(Resource Acquisition Is Initialization)의 해석

RAII라는 이름 자체에 대한 "꿈보다 해몽"

occamsrazr.net

// Example.3 Stack Unwinding
#include <iostream>
#include <string>
#include <vector>

class Person {
	std::string firstname;
	std::string lastname;
	int arbitrarynumber;
public:
	Person() : firstname(""), lastname(""), arbitrarynumber(-1){}

	Person(std::string first, std::string last, int arbitrary)
		: firstname(first), lastname(lastname), arbitrarynumber(arbitrary){
		if(arbitrarynumber == 0){
			throw std::invalid_argument("Cannot be Zero : arbitrary number");
		}
	}

	~Person(){
		std::cout << firstname << " " << lastname << " Die" << std::endl;
	}

	std::string GetName() const{ return firstname + " " + lastname; }
	int GetNum() const{ return arbitrarynumber; }
};


class Noise {
	std::string SoundIMake;
public:
	Noise(std::string sim) : SoundIMake(sim){
		std::cout << "Constructing Noise " << SoundIMake << std::endl;
	};

	~Noise(){
		std::cout << "Destructing Noise " << SoundIMake << std::endl;
	};
};

auto main() ->int{
	using namespace std;
	vector<int> v;
	Noise n1("beep 1");
	try{
		Noise n2("boop 2"); // 이녀석의 소멸자는 호출된다.
		Person Obama("Obama", "BinLaden", 0); //이녀석의 소멸자는 호출되지 않는다.
		int j = v.at(99); // 이 구문은 실행조차 되지 않는다. Person Obama의 생성자에서 먼저 에러를 던지기 때문에
	}
	catch(out_of_range& e){
		cout << " ouf of range exception " << e.what() << endl;
	}
	catch(exception& e){
		cout << e.what() << endl;
	}
}


/*
Constructing Noise beep 1
Constructing Noise boop 2
Destructing Noise boop 2
Cannot be Zero : arbitrary number
Destructing Noise beep 1
*/

 

복사했습니다!