はじめに
【C++言語】 は、C言語を拡張して1980年代に登場したプログラミング言語です。
特徴としては、C言語の「速さ・低レベル制御」を残しつつ、「オブジェクト指向」「例外処理」「標準ライブラリの拡充」などが加わりました。
【注意】このメモは、C++言語を全くしらない人間が、ChatGPTに聞いて適当に書いている、C++言語の基本的な記載方法のまとめです。
(内容は確認しながら書いているつもりですが、間違ってたらごめんなさい)
🟦 1 メモリの裏側(ヒープとグローバル変数)
1.1 メモリの構造
プログラムのメモリは大きく分けて:
・スタック(関数呼び出し)
・ヒープ(動的確保)
・グローバル領域
👉 それぞれ役割が違う
1.2 ヒープ領域とは
int* p = new int(10);
delete p;
🔹 特徴
・実行中に確保される
・手動で解放が必要
・ミスるとバグになる
1.3 グローバル変数とは
int g_value = 10;
🔹 特徴
・プログラム開始時に生成
・終了時に自動破棄
・どこからでもアクセス可能
1.4 ❗危険な組み合わせ(重要)
ヒープ × グローバル変数
👉 よくある事故
二重解放(double free)
解放後アクセス
メモリ破壊
1.5 なぜ問題になるのか
class A {
int* p;
public:
A() { p = new int(10); }
~A() { delete p; }
};
A g_obj;
👉 グローバルは終了時に自動で破棄される
👉 ライブラリや複数定義が絡むと
💥 同じメモリを2回解放 → クラッシュ
1.6 💡 実務ポイント
・グローバル変数は極力使わない
・使うなら namespace / static でスコープ制限
・ヒープは std::vector や std::string に任せる
👉 「手動deleteを減らす」
🟦 2 データの流れ(FIFO)
2.1 FIFOとは
👉 First In First Out
A → B → C(入れる)
↓
A → B → C(取り出す)
2.2 何に使うか
・メッセージキュー
・バッファ
・プロセス間通信
👉 順番保証が目的
2.3 OSでの実体
mkfifo /tmp/myfifo
👉 名前付きパイプ(FIFOファイル)
2.4 イメージ
FIFO = データの通り道
👉 「プロセス間のパイプ」
2.5 💡 挙動のポイント
・書き込み側だけだとブロックする
・読み手がいないと詰まる
・サイズ制限あり(バッファサイズ)
👉 ストリーム(流れるデータ)として扱う
🟦 3 処理の制御(セマフォ)
3.1 セマフォとは
👉 同時に使える数を制御する仕組み
3.2 イメージ
リソース数 = 2
A → OK
B → OK
C → 待ち
3.3 なぜ必要か
❌ FIFOだけだと
同時書き込み → データ破壊
👉 セマフォで制御する
3.4 実際の動き
sem_wait(sem); // ロック
// 処理
sem_post(sem); // 解放
👉 クリティカルセクションを守る
3.4 💡 実務ポイント
・mutex とほぼ同じ用途(バイナリセマフォ)
・複数許可できるのが強み(カウントセマフォ)
👉 「同時に何人OK?」を制御する
🟦 4 通信の考え方(ロングポーリング)
4.1 通常のポーリング
👉 定期的に「ある?」確認
4.2 ロングポーリング
👉 データが来るまで待つ
4.3 流れ
クライアント → リクエスト
サーバー → 待機
データ到着 → レスポンス
4.4 目的
・擬似リアルタイム通信
・無駄な通信削減
4.5 💡 実務での立ち位置
・WebSocketの前世代的技術
・サーバープッシュの簡易版
👉 「リアルタイムっぽく見せる技術」
🟦 5 実践:FIFO+セマフォでメッセージ通信
🟩 事前準備(1回だけ)
mkfifo /tmp/myfifo
🟨 Writer(送信側)
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
int main() {
const char* fifoPath = "/tmp/myfifo";
const char* semName = "/mysem";
sem_t* sem = sem_open(semName, O_CREAT, 0666, 1);
int fd = open(fifoPath, O_WRONLY);
std::string msg = "Hello from Writer\n";
sem_wait(sem);
write(fd, msg.c_str(), msg.size());
std::cout << "送信: " << msg;
sem_post(sem);
close(fd);
sem_close(sem);
return 0;
}
🟪 Reader(受信側)
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
int main() {
const char* fifoPath = "/tmp/myfifo";
int fd = open(fifoPath, O_RDONLY);
char buffer[128];
while (true) {
int n = read(fd, buffer, sizeof(buffer) - 1);
if (n > 0) {
buffer[n] = '\0';
std::cout << "受信: " << buffer;
}
}
close(fd);
return 0;
}
🟧 実行手順
① Reader起動(先に!)
g++ reader.cpp -o reader
./reader
② Writer起動(別ターミナル)
g++ writer.cpp -o writer -pthread
./writer
🧠 ポイント解説
🟩 セマフォ
sem_wait(sem);
sem_post(sem);
👉 同時書き込み防止
👉 順番制御ではなく「人数制御」
🟦 FIFO
open("/tmp/myfifo", O_WRONLY);
👉 プロセス間通信
👉 カーネル経由のストリーム
🟨 データの流れ(全体像)
Writer → FIFO → Reader
↑
セマフォで制御
👉 流れ(FIFO)+制御(セマフォ)
⚠️ 注意(超重要)
❗ 1. Readerが先に起動
👉 Writerがブロックする
❗ 2. メッセージ設計
今回は
\n 区切り
👉 実務では
・ヘッダ(長さ)
・固定長
・バイナリ構造
が必要
❗ 3. セマフォ後片付け
sem_unlink("/mysem");
👉 ゴミが残るのを防ぐ
❗ 4. 完全ではない(重要)
この構成は「簡易版」
足りないもの:
・メッセージ境界保証
・耐障害性
・再送制御
👉 本格的には
・メッセージキュー(mq)
・Redis / Kafka
などを使う
🟪 これでできること
・複数プロセス安全通信
・簡易メッセージキュー
・非同期処理の基礎
💬 最後に
👉 今日の本質はこれ
FIFO = データの流れ
セマフォ = 制御
ヒープ = メモリ管理
ロングポーリング = 通信モデル
👉 全部組み合わさると
「実システムになる」
💠ゼロから始めるプログラム学習(C++)💠
💠C++まとめ💠
💠Cまとめ💠