free(): double free detected の原因と直し方(C++のdelete)
newで確保したメモリに対してdeleteを2回呼んでしまったときに出る実行時エラーです。メモリ管理システムが不整合を検知してプロセスを強制終了させます。
エラーメッセージの読み方
free(): double free detected in tcache 2
free(): double free detected in tcache 2- ランタイム(または例外機構、assert)が不整合を検知して出したメッセージ
Aborted- この後プロセスは強制終了します(Aborted)
このエラーが出る典型パターン
パターン1
1 #include <iostream> 2 int main() { 3 int *p = new int(5); 4 delete p; 5 delete p; ^ 6 std::cout << "done" << std::endl; 7 return 0; 8 }
free(): double free detected in tcache 2
Aborted
同じポインタに対してdeleteを2回呼ぶと、メモリ管理システムが不整合を検知して強制終了します。解放直後にnullptrを代入しておけば、誤って二重に解放しても実害を防げます(nullptrへのdeleteは安全な無操作です)。
直し方: delete p; を p = nullptr; にします。
広告
広告スロット(未設定)
パターン2
1 #include <iostream> 2 int main() { 3 int *val = new int(10); 4 delete val; 5 delete val; ^ 6 std::cout << "done" << std::endl; 7 return 0; 8 }
free(): double free detected in tcache 2
Aborted
deleteされたポインタはダングリングポインタ(解放済み領域を指したままの変数)になります。それに対して再度deleteを呼ぶと管理情報の不整合が起きます。
直し方: delete val; を val = nullptr; にします。
パターン3
1 #include <iostream> 2 int main() { 3 int *counter = new int(0); 4 delete counter; 5 delete counter; ^ 6 std::cout << "done" << std::endl; 7 return 0; 8 }
free(): double free detected in tcache 2
Aborted
「deleteを呼んでも変数自体は残るので、もう一度呼んでも安全」というのは誤解です。ポインタ変数は残っても、指している先のメモリはすでに解放済みです。
直し方: delete counter; を counter = nullptr; にします。
よくある誤解
「deleteを呼んでも変数自体は残るので、もう一度deleteしても安全」というのは誤解です。deleteされたポインタは解放済みのメモリを指したままになり(ダングリングポインタ)、それに対して再度deleteを呼ぶと管理情報の不整合が起きます。解放直後にポインタをnullptrにしておけば、誤って二重に解放しても実害を防げます。
まとめ
free(): double free detected(C++のdelete)は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。