バグ:大きいサイズのファイルサイズ取得したくて正しく取得できない

Posted: 2013年08月05日

ファイルのサイズ取得で書いてしまうバグを紹介します。

プログラムプログラム:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
     FILE *fp;
     fp = fopen(argv[1],"r");
     if (fp == NULL) {
        // ファイルが開けない
        return 1;
     }

     // ファイルの最後の位置へ移動しファイルサイズを取得
     long nfileSize = _filelength(fp);

    // 処理

     delete[] pFileData;

    return 0;
 }

このプログラムにどのようにファイルサイズ取得処理にバグが存在すると思いますか?

  • この使用方法では、ファイルサイズが大きい場合、オーバーフローするため正しいファイルサイズが取得できない

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

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
     FILE *fp;
     fp = fopen(argv[1],"r");
     if (fp == NULL) {
        // ファイルが開けない
        return 1;
     }

    long long nFileSize = _filelengthi64(fp);

    return 0;
 }

解説解説:

最近では、大きいファイルが多くなりました。

_filelengthでは、4byteの結果しか返すことが出来ないため
最大で4Gのサイズしか取得ができません。
しかもunsignedではないため2Gより大きい場合は、負数になります。

この関数は、エラーの場合-1を返すため
正しくサイズが識別できない場合が存在します。

_filelengthi64では関数名から分かるとおり8byte(64bit)の値を返すため
ある程度のファイルサイズは問題なく処理がされます。

また、このサイトで例として提示した別のファイルサイズ取得方法にも同様の問題があります。

  // ファイルの最後の位置へ移動しファイルサイズを取得
  fseek(fp, 0, SEEK_END);
  long nFileSize = ftell(fp);

ftell関数は、ファイルサイズ取得ようではないため
現在のファイルポインタの位置を正しく返せば、結果が負数だとしても問題がありません。

大きいファイルを扱う場合は、型に気をつけないと痛い目にあいます

カテゴリー: バグ, プログラム | タグ: , , | コメント無し »

コメント