我是一个初学者,在 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 一直说这是内存分配问题,并不断重写代码,但没有任何帮助。我读了几次代码,但我不太确定如何解决它。
initializeFileArray()
从 loadIndexes()
内部调用,仅在程序开始时调用一次。
处理第一个文件时,在
freeFileArray()
末尾调用 FcreateList()
,将 *fileArray
设置为 NULL
。 然后,在下一次调用 initializeFileArray()
处理下一个文件之前,不会再次调用 FcreateList()
,因此您可以使用 addFileToArray
来调用 *fileArray == NULL
。 因此,尝试写入 (*fileArray)[*size]
会使程序崩溃。
(旁注:有一个名为
fileArray
的全局变量,并且让所有函数都采用一个同名的参数,即指向全局变量的 pointer,这是非常令人困惑的。)