如何修复 C 程序错误,防止在一次执行中创建多个文件?

问题描述 投票:0回答:1

我是一个初学者,在 VS 中工作,在 Microsoft 环境中,用 C 语言制作一个待办事项列表。在尝试在 Stackoverflow、Chatgpt 和一个好朋友的帮助下制作该程序后,我成功地做到了,尽管有一个错误。

当用户尝试在一次运行中创建两个文件时,程序将停止并向我发送此错误消息:在待办事项 list.exe 中的 0x00007FF623F51ED9 处抛出异常:0xC0000005:访问冲突写入位置 0x0000000000000008。

错误定位在这一行

   (*fileArray)[*size] = _strdup(fileName);

如果我关闭终端并按继续,它会再次工作,但在用户尝试一次运行创建 2 个文件后仍然会发生。

第二个文件确实在所需目录中创建,但它没有在“index_data.txt”中获得索引位置,这种情况发生在创建后出现错误的每个文件上。

如果你想重新创建错误,只需将我的目录替换为你的目录并运行程序,运行后选择 1 并键入一个名称,如“list0”,然后输入并按 A 再次返回到选择,按 1 并写入一个名称,如“ list1”按回车后应该会发生错误

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <errno.h>
#include <direct.h>
#include <io.h>

#define DIRECTORY_NAME "C:\\Users\\abood\\OneDrive\\Desktop\\TDL File"
#define INDEX_FILE "index_data.txt"
#define MAX_FILENAME_LENGTH 256


void ensureDirectoryExists(void);
void prependDirectory(char* fullPath, const char* fileName);
void initializeFileArray(char*** fileArray, int* capacity);
void loadIndexes(char*** fileArray, int* size, int* capacity);                          
void saveIndexes(char** fileArray, int size);                                           
void addFileToArray(char*** fileArray, int* size, int* capacity, const char* fileName);   
void freeFileArray(char*** fileArray, int size);
void displayFiles(char** fileArray, int size);
void FcreateList();

char input[100];
int choice = 0;
char listName[MAX_FILENAME_LENGTH];
char line[255];
FILE* fh;
bool keepGoing = true;
char fullPath[MAX_FILENAME_LENGTH];
char** fileArray = NULL;
int size = 0;
int capacity = 0;

int main() {

    ensureDirectoryExists();

    loadIndexes(&fileArray, &size, &capacity);

    do {
        printf("1. Create a new List\n");
        printf("2. Add a new Task\n");
        printf("3. Show your List\n");

        scanf("%d", &choice);
        getchar();

        switch (choice) {
        case 1:
            printf("Type a name for your list\n");
            FcreateList();
            printf("List has been created successfully\n");
            break;
        case 2:
            printf("Blank\n");
            break;
        case 3:
            printf("Blank\n");
            break;
        default:
            printf("Error opening the file\n");
        }

        printf("\nPress A to return to main Menu. Press any other Key To Exit: ");
        scanf(" %c", &input);

        system("cls");
    } while (input[0] == 'A' || input[0] == 'a');
    return 0;
}

void FcreateList() {
    scanf("%s", listName);
    getchar();
    prependDirectory(fullPath, listName);  // Prepend directory to file name
    fh = fopen(fullPath, "w");
    if (fh == NULL) {
        printf("Error creating file.\n");
        return;
    }

    system("cls");
    fclose(fh);

    addFileToArray(&fileArray, &size, &capacity, fullPath);
    printf("File '%s' created and stored at index %d.\n", fullPath, size - 1);

    system("cls");

    // Display all files with their indexes
    displayFiles(fileArray, size);

    // Save indexes to the persistent file
    saveIndexes(fileArray, size);

    // Free allocated memory
    freeFileArray(&fileArray, size);
}

void ensureDirectoryExists(void) {
    if (_access(DIRECTORY_NAME, 0) == -1) { // Check if directory exists
        if (_mkdir(DIRECTORY_NAME) != 0) { // Create the directory if it doesn't exist
            perror("Failed to create directory");
            exit(EXIT_FAILURE);
        }
    }
}

void prependDirectory(char* fullPath, const char* fileName) {
    snprintf(fullPath, MAX_FILENAME_LENGTH, "%s\\%s.txt", DIRECTORY_NAME, fileName);
}

void initializeFileArray(char*** fileArray, int* capacity) {
    *capacity = 2;  // The Array starts with 2
    *fileArray = (char**)malloc(*capacity * sizeof(char*));  // Allocate memory for the array of pointers

    // Check if malloc succeeded
    if (*fileArray == NULL) {
        perror("Failed to allocate memory for file array");
        exit(EXIT_FAILURE);
    }
}

void loadIndexes(char*** fileArray, int* size, int* capacity) {
    char indexPath[MAX_FILENAME_LENGTH];
    prependDirectory(indexPath, INDEX_FILE);  // Prepend directory to index file name

    FILE* file = fopen(indexPath, "r");
    if (!file) {
        printf("No existing index file found. Initializing empty file array.\n");
        initializeFileArray(fileArray, capacity);  // Ensure the file array is initialized
        *size = 0;
        return;
    }

    char buffer[MAX_FILENAME_LENGTH];
    *size = 0;
    initializeFileArray(fileArray, capacity);

    while (fgets(buffer, sizeof(buffer), file)) {
        buffer[strcspn(buffer, "\n")] = '\0';
        addFileToArray(fileArray, size, capacity, buffer);
    }

    fclose(file);
}

void saveIndexes(char** fileArray, int size) {
    char indexPath[MAX_FILENAME_LENGTH];
    prependDirectory(indexPath, INDEX_FILE);  // Prepend directory to index file name

    FILE* file = fopen(indexPath, "w");
    if (!file) {
        perror("Failed to open index file for writing");
        return;
    }

    for (int i = 0; i < size; i++) {
        fprintf(file, "%s\n", fileArray[i]);
    }

    fclose(file);
}

void addFileToArray(char*** fileArray, int* size, int* capacity, const char* fileName) {
    if (fileName == NULL || strlen(fileName) == 0) {
        printf("Error: Invalid file name.\n");
        return;
    }

    // Check if size is smaller or equals to the current capacity of elements
    if (*size >= *capacity) {
        *capacity *= 2; // double the capacity number
        char** newArray = (char**)realloc(*fileArray, *capacity * sizeof(char*));  // Resize the array

        // Check if realloc succeeded
        if (newArray == NULL) {
            perror("Failed to reallocate memory");
            exit(EXIT_FAILURE);
        }

        *fileArray = newArray;
    }

    // Attempt to duplicate the file name and store it in the array
    (*fileArray)[*size] = _strdup(fileName);
    if ((*fileArray)[*size] == NULL) {
        perror("Failed to duplicate file name");
        exit(EXIT_FAILURE);
    }

    (*size)++;  // Increase the size of the file array
}
void displayFiles(char** fileArray, int size) {
    printf("\nFiles and their indexes:\n");
    if (size == 0) {
        printf("No files available.\n");
        return;
    }
    for (int i = 0; i < size; i++) {
        printf("Index %d: %s\n", i, fileArray[i]);
    }
}

void freeFileArray(char*** fileArray, int size) {
    if (*fileArray) {
        for (int i = 0; i < size; i++) {
            free((*fileArray)[i]);
        }
        free(*fileArray);
        *fileArray = NULL;
    }
}

我尝试将文件命名为:file0、file1、list242、listnew、exp12 等。它不会改变任何内容。我尝试将文件命名为:list 1,文件被创建,但程序随后退出。我尝试删除创建的文件并保留index_data.txt,但出现了相同的错误。尝试使用调试器来了解问题所在,但没有任何结果。

我的朋友主要用C++编写代码,对C有一点了解,所以不幸的是他对这个问题一无所知。

Chatgpt 一直说这是内存分配问题,并不断重写代码,但没有任何帮助。我读了几次代码,但我不太确定如何解决它。

c dynamic-memory-allocation
1个回答
0
投票

initializeFileArray()
loadIndexes()
内部调用,仅在程序开始时调用一次。

处理第一个文件时,在

freeFileArray()
末尾调用
FcreateList()
,将
*fileArray
设置为
NULL
。 然后,在下一次调用
initializeFileArray()
处理下一个文件之前,不会再次调用
FcreateList()
,因此您可以使用
addFileToArray
来调用
*fileArray == NULL
。 因此,尝试写入
(*fileArray)[*size]
会使程序崩溃。

(旁注:有一个名为

fileArray
的全局变量,并且让所有函数都采用一个同名的参数,即指向全局变量的 pointer,这是非常令人困惑的。)

© www.soinside.com 2019 - 2024. All rights reserved.