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 的第二次或第三次调用有时会触发以下异常:

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)+1字节和副本,directoryName然后strcat()想要附加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 回答