0

それで、すべてのsnprintf()、sprintf()、およびセグメンテーション違反スレッドを検索して調べましたが、まだどこにもありません...

基本的に、snprintf() ステートメントが存在するだけで、コードにセグメンテーション違反が発生しているようです。簡単に言えば、はい、これは宿題です...基本的に、不足しているコードを埋める必要があり、既存のコードに触れないようにという厳しい命令を受けています。私のコードは次のようになります。

        struct dirent* dirEntryPtr;
        struct stat statBuffer;
        char *yourFileName;
        while((dirEntryPtr=readdir(dirPtr))!=NULL)
        {
            int yourFileSize;
            memset(buffer,'\0',sizeof(buffer));
            yourFileName=dirEntryPtr->d_name;
            printf("Directory entry read...%s\n",yourFileName);
            snprintf(buffer,MAX_LINE,"%s/%s",DIR_NAME,yourFileName);
            printf("Printed directory entry to buffer...\n");
            stat(buffer,&statBuffer);
            yourFileSize=statBuffer.st_size;
            printf("File size: %d\n",yourFileSize);
            if(S_ISREG(statBuffer.st_mode))
                {   
                printf("REGULAR!\n");
                snprintf(buffer,MAX_LINE,"%30s (%5d)\n",yourFileName,yourFileSize);
                printf("[%s] %30s (%5d)\n",(char *)statBuffer.st_mode,yourFileName,yourFileSize);
                }
            else
            if(S_ISDIR(statBuffer.st_mode)){
                printf("DIRECTORY!\n");
                snprintf(buffer,MAX_LINE,"%30s (dir)\n",yourFileName);
                printf("[%s] %30s (dir)\n",(char *)statBuffer.st_mode,yourFileName);}
            else
                {
                printf("OTHER!!\n");
                snprintf(buffer,MAX_LINE,"%30s (other)\n",yourFileName);
                printf("[%s] [%s] %30s (other)\n",(char*) S_ISREG(statBuffer.st_mode),(char *)statBuffer.st_mode,yourFileName);
                }                   
            printf("Writing buffer \"%s\" to client...\n",buffer);
            write(clientDescriptor,buffer,MAX_LINE);
            free(buffer);
        }
        close(clientDescriptor);
        exit(EXIT_SUCCESS);

すべての printf() は基本的にデバッグ用です。(はい、知っています、GDB を使用しますが、何年にもわたって教えられたにもかかわらず、それがどのように機能するかを理解することはできませんでした!)

簡単に言えば、現在のディレクトリ内のファイルが一度に 1 つずつ読み込まれます。通常、最初のファイルは server.c と呼ばれるもので、常に「通常の」ファイルとして正しく識別されます。ただし、その snprintf() 行が入ったときに、セグメンテーション違反が発生します。buffer は宣言された文字列です (コードの一部に触れることは許可されていませんが、指示は特に snprintf() を使用して「バッファ」にエントリを書き込むことでした-実際、私が使用している EXACT snprintf() コマンドインクルードされている外部ヘッダー ファイルで定義されている MAX_LINE バイト (80) に設定されます。以前、デバッグ目的で strnlen を使用して、DIR_NAME が 1 文字であり、yourFileName が少なくとも server.c の場合は 9 であることを確認しました。80 にはほど遠いです。

新しい変数を宣言して、snprintf() を介して 1 バイトを書き込むことさえ試みましたが、それでもセグメンテーション違反が発生しました! malloc() コマンドを使用した場合と使用しない場合の両方を試しました。

他に何を探すべきですか?私はこれについて教授に電子メールを送りましたが、正直なところ、これを提出する必要があると言われました。しかし、Cについて私が理解していることによると、これはうまくいくはずです。実際、昨日の午後は実際に機能していましたが、突然、昨夜遅くにセグメンテーション障害が発生し始めました。:(

4

2 に答える 2

2

考えられる原因は次のとおりです。

printf("[%s] [%s] %30s (other)\n",
       (char*) S_ISREG(statBuffer.st_mode),
       (char *)statBuffer.st_mode,
       yourFileName);

これは次のように指示しますprintf():

  • の戻り値を、S_ISREG()null で終了する文字列へのポインターとして扱い0ます。1sys/stat.h

    #define __S_ISTYPE(mode, mask)  (((mode) & __S_IFMT) == (mask))
    
    #define S_ISREG(mode)    __S_ISTYPE((mode), __S_IFREG)
    
  • st_modeそうではないヌル終了文字列へのポインタとして扱う(AFAIKのタイプst_modeは an ですint

OR の%d代わりにフォーマット指定子として使用することを修正するには、三項演算子を使用して、代わりに文字列リテラルを返すことができます。%sS_ISREG()

printf("[%s] [%d] %30s (other)\n",
       S_ISREG(statBuffer.st_mode) ? "regular file" : "not regular file",
       statBuffer.st_mode,
       yourFileName);

これは間違いであり、ほぼ間違いなく原因です。

char buffer[MAX_LINE];

free(buffer);

free()動的に割り当てられたものにのみ渡します:

free 関数は、ptr が指すスペースの割り当てを解除します。つまり、さらに割り当てられるようにします。ptr がヌル ポインターの場合、アクションは発生しません。それ以外の場合、引数が calloc、malloc、または realloc 関数によって以前に返されたポインターと一致しない場合、または空間が free または realloc の呼び出しによって解放された場合、動作は未定義です。

于 2012-08-15T14:56:58.163 に答える
1

別のバグ:

write(clientDescriptor,buffer,MAX_LINE);

bufferNUL で終了する文字列を指している場合、ほとんどの場合、あなたが望むものではありません。これは常に文字を書き込みMAX_LINE、NUL で停止しません。文字列を出力することfprintfをお勧めputsします。fputs

于 2012-08-15T15:49:21.187 に答える