2020年4月15日水曜日

[Linux] ファイル最後まで達したことを判定するには

こんにちは

ソフトな道をほのぼのと今日も歩きます。


今回は、Linux アプリ(C言語)でファイルリードする際、


ファイル最後に達したかどうか判定するのですが


その処理で、もしかすると、正しく判断できていないのでは?と思ったので


調べてみました。


これによって引き起こされていた現象は、


数十時間はアプリは動作するが、いきなりアプリがハングといった動作です。


推測している動作。


アプリ実行

→ファイルリード実行

→ファイル最後を超えるが、リードなのでそれとなく動いてしまう。

→スレッド動作が割り込んでくる。

→絶妙なタイミングでたまたま入って、リードしていたデータが変わる。

→スレッド処理から復帰する。

→データが化けた状態で処理を続行する為、リードデータを使用したサウンドなどの処理で誤動作

→アプリハング



下記参考までにサンプルです。

(一部、抜粋し、加工したものですので、動作するかは保証いたしかねます。)


===============================================================

#include <stdio.h>

#include <stdlib.h>

#include <sys/stat.h>


#define NORMALEND 0


int test(UCHAR* name, UINT line, char *result, UINT maxsize)

{

    FILE *fp;

    int i= 0;

    UCHAR chr[2];

    UINT length= 0;

    int count;

   struct stat statbuf;

   

      if(stat(name, &statbuf) != 0)

    {// error

        printf("[file] Error: stat() (%s %d) \n", __FILE__ , __LINE__ );

    }

    printf("[file] file size: %d (%s %d) \n ", (int)statbuf.st_size, __FILE__ , __LINE__ );

   

    //---------

    // ファイルリードの都度 countと比較していく

   fp = fopen(name, "rb");

   if (fp == NULL) {

       return ERROR_OPEN_FILE;

   }

   

    count= 0;

   

    /* ファイルの終端まで文字を読み取り表示する */

   for (i= 0; i< 0x1000; i++)

   {

        while(1)

        {

            if(count>= statbuf.st_size)

            {// サイズを超えたか?

                fclose(fp);

                return -1;

            }

            chr[0] = fgetc(fp);count++;

            if(count>= statbuf.st_size)

            {

                fclose(fp);

                return -1;

            }

           

            chr[1] = fgetc(fp);count++;

            if(chr[0]== 0 && chr[1]==0)

            {// ファイルの最後に到達(指定行見つかりませんでした。)

            // UTF-16だったので、2バイト分で見ています。

                fclose(fp);

                return -1;

            }

            else if(chr[0] == LF_CODE && chr[1] == 00)

            {// 改行コード検出

                break;

            }

        }

    }

    …

    return NORMALEND;

}


[環境]

私の使用環境は VMware 上でUbuntu14.04を使用しています。

コンパイラ: arm-linux-gnueabihf-gcc


近くの商店街は大繁盛でした。

(私は遠くから確認しただけです。)


先進国なので、

ソーシャルディスタンス系の開発とか、やりようがあるんじゃないかと

思いました。


・店を検索した時に人がいないところを教えてくれる。

・お弁当を自動販売機にする。


どうですか?


0 件のコメント:

コメントを投稿