-2

私はこのディレクトリツリーを持っています:

xy@xy:/test# find .
.
./2
./2/Asd
./2/Asd/qwe
./2/Asd/qwe/txt.txt
./1

「test」フォルダーには、4、5、6 などのディレクトリがさらに存在する可能性がありますが、asd、Asd、ASD、qwe、Qwe、QWE は一定です。目的は、次のようにすべての可能なパスを計算することです。

/test/1/ASD/QWE/txt.txt
/test/2/asd/qwe/txt.txt
/test/2/Asd/Qwe/txt.txt

その後、ファイル(txt.txt)を読み取ります

以下を作成(コピーして貼り付けて...)、しばらく動作しています。問題のある行をマークしました。

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>

char *filetosearch="txt.txt";
char *test="/test/";
char *slash="/";
char *directory[3][3] = {{"asd", "Asd", "ASD"}, {"qwe","Qwe","QWE"}};
int dircounter1=0;
int dircounter2=0;
FILE *filetosf;
char **dirpatharr=NULL;
int dirpathcount=0;
char **hdarr=NULL;
int hdarrcount=0;
char **fullpath=NULL;
int count,size;
char *dirname;
DIR  *d;
struct dirent *dir;
int main(void)
{
    d = opendir(test);
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            if( dir->d_type==DT_DIR )
            {
                dirname=dir->d_name;
                if((strcmp( dirname, ".." ) == 0) || (strcmp( dirname, "." ) == 0) )
                {
                }
                else
                {
                    hdarr=(char **)realloc(hdarr,(hdarrcount+1)*sizeof(dirname));
                    hdarr[hdarrcount]=dirname;
                    hdarrcount++;
                }
            }
            else
            {
            }
        }
    }

    closedir(d);

    for (count=0; count<hdarrcount; count++ )
    {
        for (dircounter1 = 0; dircounter1 < 3; dircounter1++ )
        {
            for (dircounter2 = 0; dircounter2 < 3; dircounter2++ )
            {
                fullpath = malloc ( strlen(test) + strlen(hdarr[count]) + strlen(slash) + strlen(directory[0][dircounter2]) + strlen(slash) + strlen(directory[1][dircounter1]) + strlen(slash) + strlen(filetosearch)+1);
                strcpy (fullpath,test);
                strcat (fullpath,hdarr[count]);
                strcat (fullpath,slash);
                strcat (fullpath,directory[0][dircounter2]);
                strcat (fullpath,slash);
                strcat (fullpath,directory[1][dircounter1]);
                strcat (fullpath,slash);
                strcat (fullpath,filetosearch);

                printf("fullpath:%s\n",fullpath);
                //    filetosf = fopen(fullpath,"r");  //THIS WILL BE THE PROBLEM!!!!

                if (filetosf){
                    fseek (filetosf, 0L, SEEK_END);
                    size=ftell(filetosf);
                    fclose(fullpath);
                    printf("file exist:%s\n",fullpath);
                }
                free (fullpath);
            }
        }
    }
}

- - - -ここでカット - - - - - - - - - -

この出力があります(私が望んでいたように):

fullpath:/test/2/asd/qwe/txt.txt
fullpath:/test/2/Asd/qwe/txt.txt
fullpath:/test/2/ASD/qwe/txt.txt
fullpath:/test/2/asd/Qwe/txt.txt
fullpath:/test/2/Asd/Qwe/txt.txt
fullpath:/test/2/ASD/Qwe/txt.txt
fullpath:/test/2/asd/QWE/txt.txt
fullpath:/test/2/Asd/QWE/txt.txt
fullpath:/test/2/ASD/QWE/txt.txt
fullpath:/test/1/asd/qwe/txt.txt
fullpath:/test/1/Asd/qwe/txt.txt
fullpath:/test/1/ASD/qwe/txt.txt
fullpath:/test/1/asd/Qwe/txt.txt
fullpath:/test/1/Asd/Qwe/txt.txt
fullpath:/test/1/ASD/Qwe/txt.txt
fullpath:/test/1/asd/QWE/txt.txt
fullpath:/test/1/Asd/QWE/txt.txt
fullpath:/test/1/ASD/QWE/txt.txt

しかし、コメント記号を削除してファイルを開く部分filetosf = fopen(fullpath,"r"); をアクティブにすると、ファイルを読み取ることができません。出力を確認すると、次のようになります。

fullpath:/test/2/asd/qwe/txt.txt
fullpath:/test//Asd/qwe/txt.txt
fullpath:/test//ASD/qwe/txt.txt
fullpath:/test//asd/Qwe/txt.txt
fullpath:/test//Asd/Qwe/txt.txt
fullpath:/test//ASD/Qwe/txt.txt
fullpath:/test//asd/QWE/txt.txt
fullpath:/test//Asd/QWE/txt.txt
fullpath:/test//ASD/QWE/txt.txt
fullpath:/test//asd/qwe/txt.txt
fullpath:/test//Asd/qwe/txt.txt
fullpath:/test//ASD/qwe/txt.txt
fullpath:/test//asd/Qwe/txt.txt
fullpath:/test//ASD/Qwe/txt.txt
fullpath:/test//asd/QWE/txt.txt
fullpath:/test//Asd/QWE/txt.txt
fullpath:/test//ASD/QWE/txt.txt

fopenこれは、表彰の前に行を印刷した場合でも発生します。なぜこうなった?

私は経験豊富なプログラマーではないので、簡単に説明してみてください。

4

2 に答える 2

2

このコードには多くの奇妙な点がありますが、すぐに明らかな明白なエラーは次のとおりです。

fullpath = malloc ( strlen(test) + strlen(hdarr[count]) + strlen(slash) + strlen(directory[0][dircounter2]) + strlen(slash) + strlen(directory[1][dircounter1]) + strlen(slash) + strlen(filetosearch)+1);

続いて、次のような一連の文字列コピーが続きます。

strcpy (fullpath,test);

注: 次fullpathのように宣言されています。

char **fullpath = NULL;

文字ポインタへのポインタを宣言します。char へのポインターではありません。警告をオンにしてから、正しく宣言した後、この変数を使用するすべての場所を再調査してください。

char *fullpath = NULL;

次に、作成しているディレクトリ名を次のように保存します (私はこの用語を大まかに使用しています)。

dirname=dir->d_name;
...
hdarr[hdarrcount]=dirname;

ただし、d_name アドレスを hdarr 動的配列の新しいスロットに保存するだけです。readdir() (または closedir()) を再度呼び出すとすぐに、アドレスは無効になります。readdir()ドキュメントから:

" readdir() によって返されたデータは、同じディレクトリ ストリームに対する readdir() の後続の呼び出しによって上書きされる可能性があります。 "

したがって、保存しているすべてのポインターは、実装が所有するメモリにあり、いつでも/どのようにでも自由にブラストオーバーできます。それらを保持したい場合は、これらのコピーを作成する必要があります (もちろん、終了したらそれらのコピーを free() します)。

これを修正する方法:

私は通常これをお勧めしませんが、あなたの場合は次のようにします: dirname で strdup() を使用します。これは貧弱な人です。「null ターム用のスペースを含めて、そのサイズの文字列バッファーを割り当て、文字列をコピーして、ポインターを私に返します。したがって、コードは次のようになります。

else
{
    char **pp = realloc(hdarr,(hdarrcount+1)*sizeof(*pp));
    if (pp)
    {
        hdaerr = pp;
        hdarr[hdarrcount++] = strdup(dir->d_name);
    }
    else
    {   // panic ensues
        exit(EXIT_FAILURE);
    }
}

これを正しく解放することを忘れないでください。hdarr の各文字列ポインタは動的に割り当てられます。それらを解放してから、配列自体を解放してください。コードの末尾 (終了直前) は次のようになります。

for (i=0;i<hdarrcount;i++)
    free(hdarr[i]);
free(hdarr);  

マイナーだが重要:

これは絶対にしないでください:

hdarr=(char **)realloc(hdarr,(hdarrcount+1)*sizeof(dirname));

失敗した場合realloc()は NULL を返し、元のデータ ポインターを失った (したがってリークした) ことになります。代わりにこれを行います:

char **pp = realloc(hdarr,(hdarrcount+1)*sizeof(*pp));
if (pp)
{
    hdaerr = pp;
    // .. continue with the rest of your assignment code
}
else
{   // allocation error, but at least you still have the 
    // old hdaerr so you can free it.
}

次に、他の誰かが指摘したように:

fclose(fullpath);

これは完全に間違っています。char ** ではなく、 をfclose()期待します。FILE *以前に開いた filetosf を渡します (そして、開いたということは、現在取り出している問題の行のコメントを外した後であるということです。それを行ったら、次のようになります。

fclose(filetosf);

注: それまでは、fopen から fclose()までのすべてのコード行をコメントアウトします。彼らがNULLファイルポインタを打つことは、私たちともう一度言います...未定義です。

于 2012-11-09T21:29:59.657 に答える
0

これは間違っています:

fclose(fullpath);
于 2012-11-09T21:09:42.303 に答える