Study: Software(SW)/SW: Language

[C++] ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ: ์˜ˆ์™ธ ์ฒ˜๋ฆฌ(try, catch, throw, exception)

DrawingProcess 2022. 8. 29. 12:32
๋ฐ˜์‘ํ˜•
๐Ÿ’ก ๋ณธ ๋ฌธ์„œ๋Š” '๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ: ์˜ˆ์™ธ ์ฒ˜๋ฆฌ'์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋†“์€ ๊ธ€์ž…๋‹ˆ๋‹ค.
ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋‹ค๋ณด๋ฉด ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ์ถฉ๋ถ„ํžˆ ์˜ˆ์ธก์ด ๊ฐ€๋Šฅํ•œ ์˜ˆ์™ธ์˜ ๊ฒฝ์šฐ๋ผ ํ• ์ง€๋ผ๋„ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌํ•œ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•˜๋Š” Exception ์ฒ˜๋ฆฌ์— ๋Œ€ํ•ด ๋‹ค๋ฃจ๋ฉฐ ์ฃผ์˜ํ•ด์•ผํ•  ์‚ฌํ•ญ์— ๋Œ€ํ•ด์„œ๋„ ์ •๋ฆฌํ•ด๋‘์—ˆ์œผ๋‹ˆ ์ฐธ๊ณ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

1. Try-Catch-Throw

  1. try ๋ฌธ : ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์ฝ”๋“œ ๋ธ”๋ก
  2. throw ๋ฌธ : try ๋ฌธ์—์„œ ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌ
  3. catch ์ ˆ : ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ์— ๋Œ€ํ•ด ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ฒ˜๋ฆฌํ•  ๋‚ด์šฉ์„ ๋‹ด์€ ์ฝ”๋“œ ๋ธ”๋ก
try { // ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์˜์—ญ
    if (์˜ˆ์™ธ ์กฐ๊ฑด) throw ์˜ˆ์™ธ ๊ฐ์ฒด; // ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ์˜์—ญ
}
catch (์˜ˆ์™ธ ๊ฐ์ฒด) { // ๋˜์ ธ์ง„ ์˜ˆ์™ธ๋ฅผ ์žก๋Š” ์˜์—ญ
    // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์˜์—ญ
}

vector์™€ ๊ฐ™์ด sequencial container์˜ ๊ฒฝ์šฐ, []operator๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  .at ๋งค์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ exception ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

try {
    std::vector<int> v(3); // ํฌ๊ธฐ๊ฐ€ 3 ์ธ ๋ฒกํ„ฐ ๋งŒ๋“ฆ
    std::cout << v.at(4);
} catch (std::out_of_range const &e) {
     std::cout << e.what() << '\n';
} catch (std::exception const &e) {
    std::cout << e.what() << '\n';
}

2. Throw (์˜ˆ์™ธ ๋˜์ง€๊ธฐ)

2.1 ๋‹ค์ค‘ catch ๊ตฌ๋ฌธ

auto exprint = [](std::exception const & e)
{
  fmt::print("{}\n", e.what());
};

try {
  throw std::runtime_error("timed out");
} catch (std::system_error const & e) {
  exprint(e);
} catch (std::runtime_error const & e) {
  exprint(e);
} catch (...) { // ๋งˆ์ง€๋ง‰ catch(...) ์—์„œ try ์•ˆ์—์„œ ๋ฐœ์ƒํ•œ ๋ชจ๋“  ์˜ˆ์™ธ๋“ค์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  fmt::print("unkown exception\n"");
}

 

  • catch๋ฌธ์€ ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐ€๋ฉด์„œ '์˜ˆ์™ธ' ๋ฐ์ดํ„ฐ์— ํƒ€๋‹นํ•œ catch๋ฌธ์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‹ˆ ์ƒ์† ๊ตฌ์กฐ์˜ ํด๋ž˜์Šค ์ž๋ฃŒํ˜•์„ ๋‘˜ ์ด์ƒ catch๋ฌธ์— ๊ธฐ์ž…ํ•˜๊ฒŒ ๋˜๋ฉด ์œ ๋„๋œ ์ˆœ์„œ๋Œ€๋กœ catch๋ฌธ์„ ๊ธฐ์ž…ํ•ฉ์‹œ๋‹ค.

2.2 Throw: std::string

string์„ throw ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ, ๋‹ค์Œ์˜ ๋งค๋‰ด์–ผ์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

//Good, because manual memory management isn't needed and this uses less heap memory (or no heap memory) so this is safer if used in a low memory situation
try { throw string("foo"); } 
catch (string s) { cout << s << endl; }
  
//Valid, but avoid manual memory management if there's no reason to use it
try { throw new string("foo"); } 
catch (string* s) { cout << *s << endl; delete s; }

//Best.  Just a pointer to a string literal, so no allocation is needed, saving on cleanup, and removing a chance for an allocation to fail.
try { throw "foo"; } 
catch (const char* s) { cout << s << endl; }

2.3 noexcept ๊ตฌ๋ฌธ

ํ™•์‹คํ•˜๊ฒŒ ์—๋Ÿฌ๋ฅผ ๋‚ด๋ณด๋‚ด์ง€ ์•Š๋Š” ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด noexcept ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • noexcept ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๋Š” ์ด์œ ๋Š” ๋‹จ์ˆœํžˆ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ฃผ๋Š” ํžŒํŠธ๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ ์ ˆ๋Œ€๋กœ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•ˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ถ”๊ฐ€์ ์ธ ์ตœ์ ํ™”๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ฐธ๊ณ ๋กœ, ํ•จ์ˆ˜์— noexcept ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์˜€๋‹ค๊ณ  ํ•ด์„œ, ํ•จ์ˆ˜๊ฐ€ ์˜ˆ์™ธ๋ฅผ ์ ˆ๋Œ€๋กœ ๋˜์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
    noexcept ๋กœ ๋ช…์‹œ๋œ ํ•จ์ˆ˜๊ฐ€ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ฒŒ ๋œ๋‹ค๋ฉด ์˜ˆ์™ธ๊ฐ€ ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ณ  ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
void func() noexcept { ... }

+ memory ๊ด€๋ จ ๋ฌธ์ œ

์ถ”๊ฐ€์ ์œผ๋กœ memory ๊ด€๋ จ ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ๋Š” Try-Catch๋กœ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชป ํ•ฉ๋‹ˆ๋‹ค.

3. Exception ์ƒ์†

exception์„ ์‚ฌ์šฉ์ž์— ๋งž์ถฐ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์†์„ ๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

#include <exception>
#include <iostream>
class Parent : public std::exception {
    public:
    // what ์€ std::exception ์— ์ •์˜๋œ ํ•จ์ˆ˜๋กœ, ์ด ์˜ˆ์™ธ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์ž์—ด์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค.
    virtual const char* what() const noexcept override { return "Parent!\n"; }
};
class Child : public Parent {
    public: const char* what() const noexcept override { return "Child!\n"; }
};

4. Exception ์‚ฌ์šฉ์‹œ ์ฃผ์˜ํ•  ๊ฒƒ

4.1 Exception ์ฃผ์˜ ์‚ฌํ•ญ

  • ์˜ˆ์™ธ์ฒ˜๋ฆฌ try-catch๋Š” ๊น”๋”ํ•˜๊ธด ํ•˜์ง€๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ํ• ์ˆ˜๋ก ํ”„๋กœ๊ทธ๋žจ ์„ฑ๋Šฅ์—๋Š” ์•…์˜ํ–ฅ์„ ๋ฏธ์ณ์„œ ๋ฌด์ž‘์ • ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.
  • ์ถฉ๋ถ„ํžˆ ์˜ˆ์ธก์ด ๊ฐ€๋Šฅํ•œ ์˜ˆ์™ธ์˜ ๊ฒฝ์šฐ, ์˜ˆ์™ธ๋ฅผ ํ•ด์ฃผ๊ธฐ๋ณด๋‹ค๋Š” ์ €๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฒƒ์„ ์ค‘์ ์œผ๋กœ ๋‘ฌ์•ผ๋ฉ๋‹ˆ๋‹ค.
  •  ์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋ฒ„๊ฐ™์€ ๊ฒฝ์šฐ์—์„œ ์ž…๋ ฅ๊ฐ’์— ์˜ค์—ผ์ด ๋ฐœ์ƒํ•˜๋Š”๋“ฑ์˜ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ฒจ ํฐ ๋ฌธ์ œ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ์•ˆ๋˜๊ธฐ์— ํŠน์ • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ๋„ ์„œ๋ฒ„๊ฐ€ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ณ  ๋ฒ„ํ‹ฐ๋„๋ก ํ•˜๋Š” ๊ฒฝ์šฐ์— ์ข…์ข… ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

4.2 ๊ทผ๋ฐ Exception ์€..? ์„ฑ๋Šฅ ์•…์˜ํ–ฅ...

์–ผํ• ๋ณด๋ฉด… ๊ฐ€๋…์„ฑ๋„ ์žˆ๊ณ  ๋ชฐ์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ๊ดœ์ฐฎ๊ณ  ‘์˜ค ์ด๊ฑฐ ์จ์•ผ ๊ฒ ๋‹ค!’ ์ƒ๊ฐํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ... ์‚ฌ์šฉํ•˜๋ฉด ํ• ์ˆ˜๋ก ํ”„๋กœ๊ทธ๋žจ ์„ฑ๋Šฅ์—๋Š” ์•…์˜ํ–ฅ์„ ๋ฏธ์ณ์„œ ๋ฌด์ž‘์ • ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  • ํ”„๋กœ๊ทธ๋žจ ์šฉ๋Ÿ‰๋„ ์ปค์ง€๊ณ , ํ”„๋กœ๊ทธ๋žจ ์„ฑ๋Šฅ์ด ๋ˆˆ์— ๋„๊ฒŒ ๋А๋ ค์ง‘๋‹ˆ๋‹ค(์Šคํƒ ๋˜๊ฐ๊ธฐ ๋“ฑ ๋•Œ๋ฌธ์—)
  • ๋™์  ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ ์•ˆ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ,
  • ๊ฒฐ์ •์ ์ธ ์—๋Ÿฌ๋ฅผ ๋ชป ์ฐพ๋Š” ๊ฒฝ์šฐ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ... ์ถฉ๋ถ„ํžˆ ์˜ˆ์ธก์ด ๊ฐ€๋Šฅํ•œ ์˜ˆ์™ธ์˜ ๊ฒฝ์šฐ, ์˜ˆ์™ธ๋ฅผ ํ•ด์ฃผ๊ธฐ๋ณด๋‹ค๋Š” ์ €๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์ค‘์ ์œผ๋กœ ๋‘ฌ์•ผ๋ฉ๋‹ˆ๋‹ค.

+ ์—ฌ๊ธฐ์„œ ์Šคํƒ ๋˜๊ฐ๊ธฐ๋ž€? ํ•จ์ˆ˜ ์‹คํ–‰ ์ค‘ throw๋ฅผ ๋งŒ๋‚˜๋ฉด ๋Œ€์‘๋˜๋Š” catch๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœ์›์œผ๋กœ.

  • ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋Š” ์Šคํƒ์— ๊ฐ ํ•จ์ˆ˜์˜ ์Šคํƒํ”„๋ ˆ์ž„์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • ํ˜ธ์ถœ ์ง์ „ ํ˜ธ์ถœ ํ•จ์ˆ˜(์„œ๋ธŒ๋ฃจํ‹ด)๊ฐ€ ๋๋‚˜๊ณ  ๋Œ์•„์˜ฌ ์ฃผ์†Œ๋ฅผ ํ˜ธ์ถœ ์Šคํƒ(call stack)์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
  • ํ˜ธ์ถœ ์Šคํƒ์— ๋“ค์–ด๊ฐ€๋Š” ์ •๋ณด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • ์„œ๋ธŒ๋ฃจํ‹ด ์ข…๋ฃŒ ์งํ›„ ๋Œ์•„๊ฐˆ ์ฃผ์†Œ
    • ์ง€์—ญ ๋ณ€์ˆ˜
    • ๋งค๊ฐœ ๋ณ€์ˆ˜
  • ํ•จ์ˆ˜๊ฐ€ ๋ฆฌํ„ดํ•  ๋•Œ ์Šคํƒํ”„๋ ˆ์ž„์€ ์ •ํ™•ํ•˜๊ฒŒ ํ˜ธ์ถœ ์ง์ „์œผ๋กœ ๋Œ์•„๊ฐ€๋ฉฐ, ํ˜ธ์ถœ ์Šคํƒ์— ์žˆ๋Š” ์ •๋ณด๋Š” throw ๋ฐœ์ƒ์‹œ ์ „๋ถ€ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ์ด ์ƒ์œ„ํ•จ์ˆ˜ catch๋กœ ์ „์ด๋˜๋Š” ๊ณผ์ •์—์„œ ์ค‘๊ฐ„์— ์žˆ๋˜ ์˜ค๋ฅ˜๋“ค์ด ์‚ฌ๋ผ์ง€๊ณ  ํ•ด๋‹น ์Šคํ…์˜ ์˜ค๋ฅ˜ ์ •๋ณด๋งŒ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.
  • ์ค‘๊ฐ„์— ์žˆ๋˜ ์˜ค๋ฅ˜๋“ค๊นŒ์ง€ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์œผ๋ฉด?

4.3 try-exception benchmark ์ธก์ •

 

์ฐธ๊ณ 

๋ฐ˜์‘ํ˜•