0

私は現在、特定のフォルダー内のすべてのファイルのサイズを配列に格納する必要があるプログラムを作成しています。Code::Blocks をリリース モードで実行するとプログラムがクラッシュしますが、デバッグ モードでは実行されます。Mac OS の XCode でも問題なく動作します。コードは次のとおりです。

#define MALLOC_ERROR -1
#define DIR_ACCESS_ERROR -2
#define FILE_ACCESS_ERROR -3
#define FILE_OPEN_ERROR -4
#define OUTPUT_FILE_OPEN_ERROR -5

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

int compare(const void*, const void*);
int getFileSizeMarginNumbers(char[], int, unsigned long int*);

int main(void){

    FILE *out;
    int n;
    int i, count = 1;
    unsigned long int *fileSizeMarginNumber;
    char directoryName[] = "C:\\Users\\Борис\\Desktop\\new\\";
    char outputFilePath[] = "C:\\Users\\Борис\\Desktop\\out.txt";

    printf("Enter number of files in directory:");
    scanf("%d", &n);

    if (!(fileSizeMarginNumber = (unsigned long int*)malloc(n*sizeof(unsigned long int)))){
        printf("Not enough memory");
        return MALLOC_ERROR;
    }
    switch (getFileSizeMarginNumbers(directoryName, n, fileSizeMarginNumber)) {
        case MALLOC_ERROR:
            return MALLOC_ERROR;
            break;

        case DIR_ACCESS_ERROR:
            return DIR_ACCESS_ERROR;
            break;

        case FILE_ACCESS_ERROR:
            return FILE_ACCESS_ERROR;
            break;

        case FILE_OPEN_ERROR:
            return FILE_OPEN_ERROR;
            break;
    }

    qsort(fileSizeMarginNumber, n, sizeof(unsigned long int), compare);

    if (!(out = fopen(outputFilePath, "w"))){
        printf("Unable to open output file");
        return OUTPUT_FILE_OPEN_ERROR;
    }

    for (i=1; i<n; ++i) {
        if (fileSizeMarginNumber[i] == fileSizeMarginNumber[i - 1])
            ++count;
        else{
            fprintf(out, "%ldKB - %ldKB: %d file(s);\n", (fileSizeMarginNumber[i - 1] - 1)*16, fileSizeMarginNumber[i - 1]*16, count);
            count = 1;
        }
    }

    fprintf(out, "%ldKB - %ldKB: %d files;\n", (fileSizeMarginNumber[i - 1] - 1)*16, fileSizeMarginNumber[i - 1]*16, count);

    return 0;
}

int getFileSizeMarginNumbers(char directoryName[], int n, unsigned long int *fileSizeMarginNumber){

    int i, fileDescriptor;
    struct dirent *file;
    struct stat currentSize;
    DIR *directory;
    FILE *buf;

    if (!(directory = opendir(directoryName))) {
        printf("Unable to get access to the specified directory");
        return DIR_ACCESS_ERROR;
    }

    for (i=0;i<2;++i){
        if (!(file = readdir(directory))) {
            printf("Unable to get access to a file in the specified directory");
            return FILE_ACCESS_ERROR;
        }
    }

    for (i=0; i<n; ++i) {
        if (!(file = readdir(directory))) {
            printf("Unable to get access to a file in the specified directory");
            return FILE_ACCESS_ERROR;
        }
        printf("%s", strcat(strdup(directoryName), file->d_name));
        if (!(buf = fopen(strcat(strdup(directoryName), file->d_name), "r"))){
            printf("Unable to process a file in the specified directory");
            return FILE_OPEN_ERROR;
        }

        fileDescriptor = fileno(buf);
        fstat(fileDescriptor, &currentSize);
        fileSizeMarginNumber[i] = (unsigned long int)truncl(currentSize.st_size/(1024*16)) + 1;

        fclose(buf);
    }

    return 0;
}

int compare(const void *a, const void *b){

    if ((*(long int*)a - *(long int*)b) < 0)
        return -1;
    else if ((*(long int*)a - *(long int*)b) == 0)
        return 0;
    else
        return 1;
}

問題は次のブロックにあるようです。

for (i=0; i<n; ++i) {
        if (!(file = readdir(directory))) {
            printf("Unable to get access to a file in the specified directory");
            return FILE_ACCESS_ERROR;
        }
        printf("%s", strcat(strdup(directoryName), file->d_name));
        if (!(buf = fopen(strcat(strdup(directoryName), file->d_name), "r"))){
            printf("Unable to process a file in the specified directory");
            return FILE_OPEN_ERROR;
        }

        fileDescriptor = fileno(buf);
        fstat(fileDescriptor, &currentSize);
        fileSizeMarginNumber[i] = (unsigned long int)truncl(currentSize.st_size/(1024*16)) + 1;

        fclose(buf);
    }

プログラムは、フォルダー内のすべてのファイルを段階的に開くことになっています。ただし、fopen の 2 回目または 3 回目の呼び出しで、次の例外が発生することがあります。

Program received signal SIGSEGV, Segmentation fault.
In ntdll!RtlLargeIntegerToChar () (C:\Windows\system32\ntdll.dll)

プログラムを実行している場所へのこの依存関係を理解し​​ていません。あなたの助けに非常に感謝していました.

事前にどうもありがとうございました。

4

1 に答える 1

0

それstrcat()fopen()正しくありません:

strcat(strdup(directoryName), file->d_name)

最初にバイトとコピーをstrdup()割り当て、次にそのコピーに追加します。ただし、余分なスペースが割り当てられていないため、セグ フォールトが発生する可能性があります。代わりにそのようなことをしてください:strlen(directoryName)+1directoryNamestrcat()file->d_name

char *pathname = MALLOC( strlen(directoryName) + strlen(file->d_name) + 1 );
strcpy( pathname, directoryName );
strcat( pathname, file->d_name );

free(pathname)必要がなくなったら忘れずに

于 2013-10-04T12:55:53.097 に答える