変数初期化の重要性

とある(比較的広く使われている)C言語のプログラムをデバッグしていたのだけれど、なんか初期化されていない変数を使っていそうな感じの箇所が多い。

そこで、全体をgcc -Wmaybe-uninitializedでチェックしてみると、結構出てきた。
(デバッグの話はこれで終わり。)

もっとも、maybeだけあって、必ず妥当な警告を出すわけではなくて、

void *ptr;
if (cond) {
    ptr = hoge_alloc();
    *ptr = ...
}
...
if (cond)
    hoge_free(ptr);

みたいなコードでcondが変化しない場合、特に問題は起きないはずだけれど、「初期化してないかもしれない変数ptrを使っている」と警告を出してしまう。

でもこれって、そういうのに引っかからないように、例えば

void *ptr = NULL;
if (cond) {
    ptr = hoge_alloc();
    *ptr = ...
}
...
if (ptr != NULL)
    hoge_free(ptr);

みたいにした方が変なバグ入り込みにくいんじゃないかね?
よくある「hoge_free(NULL)は何もしない」って仕様だったら後半のifも不要。

で、恐ろしいのは、

uid_t uid;
if (name != NULL) {
    pwd = getpwnam(name);
    ...
    uid = pwd->uid;
}
...
if (setuid(uid) < 0) {
    ...
}

みたいなやつで、uidに変な値が入っててもアレだけど、普通に0で初期化されているともっと「やばいですね!」(プリコネR風に)

uidの初期値をnobody的な値にしておいてもいいかもしれないけど、

uid_t uid;
if (name == NULL)
    return ERROR;
pwd = getpwnam(name);
...
uid = pwd->uid;
...
if (setuid(uid) < 0) {
    ...
}

とか、最初から-Wmaybe-uninitializedに引っかからないような書き方に改めた方が(≒if文の中で初期化して外で使うのをやめた方が)良い気がする。

(気がするというか、当然そうするもんだと思ってたけど、意外にそうでないコードが多いようで。)