MeWrite Docs

C++: double free or corruption

C++で同じメモリを二重解放した場合のエラー

概要

C++で同じメモリ領域を2回以上解放しようとした場合に発生するエラーです。ヒープの破損を引き起こす深刻なバグです。

エラーメッセージ

*** Error in `./program': double free or corruption (fasttop): 0x0000000001234567 ***
Aborted (core dumped)

または

free(): double free detected in tcache 2

原因

  1. 同じポインタを複数回delete: 明示的に2回削除
  2. 浅いコピー: コピーされたオブジェクトが同じメモリを共有
  3. デストラクタの重複呼び出し: 手動デストラクタ呼び出し後の自動解放
  4. ダングリングポインタ: 解放済みメモリへの参照

解決策

1. delete後はnullptrを設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 悪い例
int* ptr = new int(42);
delete ptr;
delete ptr;  // 二重解放!

// 良い例
int* ptr = new int(42);
delete ptr;
ptr = nullptr;  // nullptrに設定
delete ptr;     // nullptrのdeleteは安全

2. スマートポインタを使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <memory>

// 悪い例:生ポインタ
int* ptr = new int(42);
// 複雑なロジックで複数回deleteされる可能性

// 良い例:unique_ptr
std::unique_ptr<int> ptr = std::make_unique<int>(42);
// 自動的に管理される、二重解放の心配なし

// 共有が必要な場合:shared_ptr
std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = ptr1;  // 参照カウントで管理

3. コピーコンストラクタを正しく実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class MyClass {
    int* data;
public:
    MyClass(int value) : data(new int(value)) {}

    // 悪い例:デフォルトコピー(浅いコピー)
    // MyClass(const MyClass& other) = default;

    // 良い例:深いコピー
    MyClass(const MyClass& other) : data(new int(*other.data)) {}

    // ムーブコンストラクタ
    MyClass(MyClass&& other) noexcept : data(other.data) {
        other.data = nullptr;
    }

    ~MyClass() { delete data; }
};

4. Rule of Three/Five を守る

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Resource {
    char* buffer;
public:
    Resource(size_t size) : buffer(new char[size]) {}

    // コピーコンストラクタ
    Resource(const Resource& other);

    // コピー代入演算子
    Resource& operator=(const Resource& other);

    // デストラクタ
    ~Resource() { delete[] buffer; }

    // C++11以降:ムーブコンストラクタ
    Resource(Resource&& other) noexcept;

    // ムーブ代入演算子
    Resource& operator=(Resource&& other) noexcept;
};

5. AddressSanitizerで検出

1
2
3
g++ -fsanitize=address -g program.cpp -o program
./program
# 詳細なエラー情報が表示される

6. valgrindで検出

1
valgrind --track-origins=yes ./program

よくある間違い

  • STLコンテナに生ポインタを格納してコピー
  • 例外発生時のリソース解放漏れ
  • コピー禁止クラスでコピーを許可している
  • 継承時の仮想デストラクタ忘れ

C++ の他のエラー

最終更新: 2025-12-09