経緯
42tokyoでC言語の課題を解いている途中で、メモリリークが発生していると機械採点に言われてしまいました。しかし、どこで何がメモリリークしているのかわからずに困っていました。そこで、メモリリークの確認方法を調べてみた内容をメモとしてまとめました。ただ、Guacamoleのssh-cluster上でのチェック方法なので、42の生徒以外にはあんまり役に立たないかもしれません(笑)。
Guacamoleとは
Guacamoleって何やねん、という方はこちらとかが詳しいと思います。個人的に思うGuacamoleの大きな特徴としては、下のような感じかなと思います。
- ブラウザ上でリモートアクセスできる
- 複数人で共同で操作ができる
- ファイルとかもアップロードできる
手順
関数内のどこでメモリリークしているか、確認する手順をまとめます。今回は自作したft_split関数を例に挙げてやっていきます。この関数の動作としては、第一引数に文字列を渡し、第二引数に区切り文字を渡すと、区切り文字で区切られた配列が戻り値として返ってきます。ft_split("ABCDE", 'C')だと、[["AB"], ["DE"]]のようなイメージです。
1. 無限ループする関数を作成する
下のようなft_splitを呼び出した後に無限ループする関数を作成します。
int main(void)
{
int index;
char **tab;
tab = ft_split("AxBxCCCxDDDDxEExxxF", 'x');
index = 0;
while (tab[index])
free(tab[index++]);
free(tab);
while (1);
}
2. バックグラウンド実行して、メモリリークチェック
上のスクリプトをコンパイルしたあと、バックグラウンドで実行します。
$ ./a.out 0 & (&をつけることで、バックグラウンドで実行)
$ leaks a.out
自分は最初にleaksコマンドを実行したとき、下の写真のようなメッセージが出てきました。
一番下のROOT LEAKというやつがメモリリークしています、と言っています。自分は、ft_substrというmallocする自作関数の結果をそのままft_strtrimという自作関数に引数として渡していたのですが、ft_substrで確保したメモリ領域をそのままにしていました。なので、そこをfreeするように修正すると、下のようなメッセージに変わり、メモリリークは発生していませんでした。
leaksコマンドを実行した後は、以下のコマンドで実行プロセスをkillしてあげてください。じゃないと、関数が無限ループのままなので(笑)。
$ ps (a.outの実行プロセスを確認)
$ kill [プロセスID]
まとめ
あまり多くの人の役に立つような記事ではありませんが、メモ代わりにまとめてみました。C言語はメモリ管理が大変だな思いつつ、でもその煩わしさ含めて最近はC言語が好きになってきました。
間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。