【C言語】
初期化されていない自動変数
(ローカル変数)の値はゴミ

warning: ‘ptr’ is used uninitialized

警告:未初期化変数を使用した
[-Wuninitialized]


■1.初期化されていない自動変数の問題例

#include    <stdio.h>
int main(void){
    int gomi;
    printf("%d\n",gomi); 
}

初期化していない自動変数の値はゴミです。

お客様へのバグの報告はいつも大変な作業ですが、
特にゴミの問題はプログラムに詳しくないお客様にも
問題である事が明確なので言い訳ができません。
C言語プログラマはこの問題を出さないように
常に気を付けましょう。


■2.初期化されていないポインタの問題例

int main(void){  
    int     *ptr;
    *ptr = 0;//★NGこれはポインタの初期化ではない
}

初期化していない自動変数のポインタの値もゴミですので
メモリの何処を指しているのかわかりません。
何処を指しているかわからないポインタの指す先に
書き込みをすると
多くの場合セグメンテーションホールドを起こします。


■3.警告してくれない関数を跨いだ問題例

#include <stdio.h>
void f1(int *p) {
    printf("%p\n",p);
    *p = 0 ;//初期化している
}
void f2(int *p) {
    printf("%p\n",p);
    //初期化していない
}
int main(void) {
    int     x,y;
    
    f1(&x) ; 
    f2(&y) ;//この行だけでは問題の有無を判断できない
    
    printf("%d\n",x);
    printf("%d\n",y);
}


gcc等の最近のコンパイラは未初期化を検出してくれますが、
完全に検出してくれるわけではありません。

関数を跨いだりファイルを跨いだりした
未初期化の検出は非常に困難で未検出となる場合があります。


このサンプルでgccは警告してくれません。

高額な静的解析ツールのカタログでは未初期化変数問題の検出可能をうたう物も多いですが、
実際のプロジェクトのソースコードを解析すると
タイムアウトとか、メモリ不足とかで
解析中断してしまうものが多いようです。


■4.推奨する対策

#include <stdio.h>
int  f1(void) {
    return 0 ;
}
int f2(void) {
    return ;//返却値を忘れてもコンパイラが警告を出してくれる
}
int main(void) {
    int x = f1() ; 
    printf("%d\n",x);

    int y = f2() ;
    printf("%d\n",y);
}

未初期化を防ぐ方法として以下のスタイルがあります。
1:変数宣言、値設定、値参照の行間を可能な限り縮める。
  C99が使用できるなら変数参照の直前で
  変数宣言と初期化を同時に行う。
2:関数のアドレス渡しによる値設定ではなく戻り値を使う
  func(&x) ; ではなくて
  x = func() ;とする。func()側で戻り値を設定し忘れても
   コンパイラや静的解析ツールが警告を出してくれます。

参考:

CWE-457: Use of Uninitialized Variable