メモリリークのチェック
このステップでは、強力なメモリデバッグツールであるValgrindを使って、C++におけるメモリリークを検出し防止する方法を学びます。メモリリークは、動的に割り当てられたメモリが適切に解放されない場合に発生し、プログラムが増え続けるメモリを消費します。
まず、ターミナルでValgrindをインストールします。
sudo apt update
sudo apt install -y valgrind
WebIDEで ~/project
ディレクトリに memory_leak.cpp
を作成して、メモリリークの例を作成します。
touch ~/project/memory_leak.cpp
memory_leak.cpp
に以下のコードを追加します。
#include <iostream>
class Resource {
public:
Resource(int value) : data(value) {
std::cout << "Resource created: " << data << std::endl;
}
~Resource() {
std::cout << "Resource destroyed: " << data << std::endl;
}
private:
int data;
};
void createMemoryLeak() {
// これはメモリリークを引き起こします。リソースが削除されていません。
Resource* leak = new Resource(42);
// 欠落: delete leak;
}
int main() {
// 複数のメモリリークをシミュレートします。
for (int i = 0; i < 3; ++i) {
createMemoryLeak();
}
return 0;
}
デバッグシンボル付きでプログラムをコンパイルします。
g++ -g memory_leak.cpp -o memory_leak
Valgrindを実行してメモリリークを検出します。
valgrind --leak-check=full./memory_leak
Valgrindの出力の例:
==1988== Memcheck, a memory error detector
==1988== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1988== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1988== Command:./memory_leak
==1988==
Resource created: 42
Resource created: 42
Resource created: 42
==1988==
==1988== HEAP SUMMARY:
==1988== in use at exit: 12 bytes in 3 blocks
==1988== total heap usage: 5 allocs, 2 frees, 73,740 bytes allocated
==1988==
==1988== 12 bytes in 3 blocks are definitely lost in loss record 1 of 1
==1988== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1988== by 0x109241: createMemoryLeak() (memory_leak.cpp:19)
==1988== by 0x109299: main (memory_leak.cpp:26)
==1988==
==1988== LEAK SUMMARY:
==1988== definitely lost: 12 bytes in 3 blocks
==1988== indirectly lost: 0 bytes in 0 blocks
==1988== possibly lost: 0 bytes in 0 blocks
==1988== still reachable: 0 bytes in 0 blocks
==1988== suppressed: 0 bytes in 0 blocks
==1988==
==1988== For lists of detected and suppressed errors, rerun with: -s
==1988== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
ご覧の通り、Valgrindは3つのブロックにおける12バイトのメモリリークを検出しました。createMemoryLeak()
で作成された Resource
オブジェクトが削除されておらず、メモリリークを引き起こしています。
メモリリークを修正するには、コードを変更してリソースを適切に削除します。
void createMemoryLeak() {
// 動的に割り当てられたリソースを適切に削除する
Resource* leak = new Resource(42);
delete leak; // この行を追加してメモリリークを防止する
}
メモリリークが修正されたことを確認するために、再度コンパイルしてValgrindでプログラムを実行します。
g++ -g memory_leak.cpp -o memory_leak
valgrind --leak-check=full./memory_leak
==2347== Memcheck, a memory error detector
==2347== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2347== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==2347== Command:./memory_leak
==2347==
Resource created: 42
Resource destroyed: 42
Resource created: 42
Resource destroyed: 42
Resource created: 42
Resource destroyed: 42
==2347==
==2347== HEAP SUMMARY:
==2347== in use at exit: 0 bytes in 0 blocks
==2347== total heap usage: 5 allocs, 5 frees, 73,740 bytes allocated
==2347==
==2347== All heap blocks were freed -- no leaks are possible
==2347==
==2347== For lists of detected and suppressed errors, rerun with: -s
==2347== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
メモリリークに関する重要なポイント:
- 常に動的に割り当てられたメモリを
delete
する
unique_ptr
や shared_ptr
のようなスマートポインタを使用する
- Valgrindを使ってメモリリークを検出する
- より良いデバッグ情報を得るために
-g
フラグ付きでコンパイルする