バグ:環境変数の変更処理でたまに異常な状況となる

Posted: 2013年06月17日

文字列中に環境変数を変更する処理でよく書いてしまうバグを紹介します。

プログラムプログラム:

 #include <stdio.h>
 $include <winbase.h>

 int main(int argc, char *argv[])
 {
    TCHAR *pszEnv;
    pszEnv = _tgetenv(_T("JAVA_HOME"));

    if (strlen(pszEnv) == 0) {
        strcpy(pszEnv, _T("C:Program filesJavabin"));
    }

    // 処理

    return 0;
 }

このプログラムにどのように文字列中に環境変数を変更する処理が間違えていると思いますか?

  • 環境変数が存在しない場合は、NULLが返されるが考慮されていない
  • getenvで返却される値を変更する場合は、putenvを使用すべき

改善版プログラム改善版プログラム:

 #include <stdio.h>
 $include <winbase.h>
 #include <io.h>

 int main(int argc, char *argv[])
 {
    TCHAR *pszEnv[256];
    TCHAR *pszTempEnv = _tgetenv(_T("JAVA_HOME"));
    if (pszTempEnv != NULL) {
        // 読み込んだ値をコピー
        strncpy(pszEnv, pszTempEnv, 255);
    }

    if (pszEnv == NULL) {
        // 定義されていない場合
        strcpy(pszEnv,  _T("C:Program filesJavabin"));
        _tputenv(_T("JAVA_HOME"), pszEnv);
    }

    // 処理

    return 0;
 }

解説解説:

getenvで取得する値は、putenvなど他の関数の影響で
ポインターアドレスが変化します。

そのため取得した場すぐに使用し使い回さないか
または、コピーして使用することを推奨しています

すぐに使用するにしてもどのような処理をするかわからない関数などの引数に使用した場合
時間が経過後予想外の挙動をするでしょう

その他にgetenvで取得したポインターに
上書きをした場合、様々な要因があるためあまり推奨されないでしょう

  • アドレス先の値が変更され期待される環境変数とは異なる値を変更する
  • システムが確保している領域を超えて書いてしまい、他の環境変数などに影響を出す。
カテゴリー: バグ, プログラム | タグ: , , | コメント無し »

コメント