CPP04 1.0
読み取り中…
検索中…
一致する文字列を見つけられません
TestRaii.cpp
[詳解]
1/* ************************************************************************** */
2/* */
3/* ::: :::::::: */
4/* TestRaii.cpp :+: :+: :+: */
5/* +:+ +:+ +:+ */
6/* By: kamitsui <kamitsui@student.42tokyo.jp> +#+ +:+ +#+ */
7/* +#+#+#+#+#+ +#+ */
8/* Created: 2025/06/03 20:21:33 by kamitsui #+# #+# */
9/* Updated: 2025/06/03 20:23:25 by kamitsui ### ########.fr */
10/* */
11/* ************************************************************************** */
12
18#include "Animal.hpp"
19#include "Cat.hpp"
20#include "Dog.hpp"
21#include "ScopedPointer.hpp" // 自作したスマートポインタ
22#include <cstdlib> // EXIT_FAILURE のために必要
23#include <iostream>
24#include <new> // std::bad_alloc のために必要
25#include <string>
26
27// --- カスタムアロケータのグローバル変数 ---
28static int g_alloc_counter = 0;
29static int g_fail_at_alloc_count = -1; // -1 なら常に成功
30
31// --- new 演算子のオーバーロード (グローバル) ---
32// これはC++98互換性を意識した一般的なオーバーロード例
33void *operator new(std::size_t size) throw(std::bad_alloc) {
34 if (g_fail_at_alloc_count != -1) {
35 g_alloc_counter++;
36 std::cerr << ">>> Debug: operator new called. Count: " << g_alloc_counter << ", Size: " << size << " bytes."
37 << std::endl;
38 if (g_alloc_counter >= g_fail_at_alloc_count) {
39 std::cerr << "--- Forcing std::bad_alloc at allocation #" << g_alloc_counter << " ---" << std::endl;
40 throw std::bad_alloc(); // 意図的に例外をスロー
41 }
42 }
43 // 通常のメモリ割り当てを行う
44 // C++98 では std::malloc を使用することが多い
45 void *ptr = std::malloc(size);
46 if (!ptr) {
47 std::cerr << "Actual malloc failure!" << std::endl;
48 throw std::bad_alloc(); // 本当に割り当てが失敗した場合
49 }
50 return ptr;
51}
52
53// delete 演算子のオーバーロード (対応する delete も必要)
54void operator delete(void *ptr) throw() { std::free(ptr); }
55
56int testRaii(void) {
57 std::cout << "--- Test RAII( Resource Acquisition Is Initialization ) ---" << std::endl;
58
59 // ポインタ変数ではなく、ScopedPointer のインスタンスをスタックに作成する
60 // これらは main 関数のスコープを抜けるときに自動的に解放される
64
65 try {
66 // --- 割り当て失敗のシミュレーション設定 ---
67 g_alloc_counter = 0; // カウンタをリセット
68 // 3回目の new (i.reset(new Cat())) で失敗するように設定
69 // new Animal()が1回目、new Dog()が2回目、new Cat()が3回目
70 g_fail_at_alloc_count = 3;
71
72 // new で割り当てた生ポインタを ScopedPointer オブジェクトのコンストラクタに直接渡す
73 // または reset() を使用する
74 meta.reset(new Animal()); // 1回目の new (成功)
75 j.reset(new Dog()); // 1回目の new (成功)
76 i.reset(new Cat()); // 3回目の new (ここで失敗がシミュレートされる)
77
78 // もし C で例外がスローされたとしても、
79 // A と B で割り当てられたメモリは、meta と j のデストラクタが
80 // 自動的に呼ばれることで解放される。
81
82 std::cout << j->getType() << " " << std::endl;
83 std::cout << i->getType() << " " << std::endl;
84 i->makeSound();
85 j->makeSound();
86 meta->makeSound();
87
88 // ここで明示的に delete する必要はない
89 // delete meta;
90 // delete j;
91 // delete i;
92
93 } catch (const std::bad_alloc &e) {
94 std::cerr << "Error: Memory allocation failed! " << e.what() << std::endl;
95 // 例外捕捉後、ScopedPointer のデストラクタが自動で呼ばれ、
96 // 既に割り当てたメモリが解放されることが保証される。
97 return EXIT_FAILURE;
98 } catch (const std::exception &e) {
99 std::cerr << "An unexpected standard error occurred: " << e.what() << std::endl;
100 return EXIT_FAILURE;
101 } catch (...) {
102 std::cerr << "An unknown error occurred." << std::endl;
103 return EXIT_FAILURE;
104 }
105
106 // main 関数が終了するとき、meta, j, i の ScopedPointer オブジェクトがスコープを抜ける。
107 // その際にそれぞれのデストラクタが呼ばれ、内部の生ポインタが指すメモリが解放される。
108
109 return 0;
110}
int testRaii(void)
Definition TestRaii.cpp:56
The Animal class represents a generic animal.
Definition Animal.hpp:37
The Cat class represents a feline animal.
Definition Cat.hpp:33
The Dog class represents a canine animal.
Definition Dog.hpp:33
void reset(T *ptr=0)
T endl(T... args)
Declares the abstract Animal base class.
Declares the Cat class.
Declares the Dog class.
ScopedPointer Class is Custom smart pointer with RAII pattern applied.
T free(T... args)
T malloc(T... args)
T what(T... args)