I am a beginner, working in VS, in a Microsoft environment, making a To Do List in C. After trying to make the program with the help of Stackoverflow, Chatgpt and a good friend, I manged to do it, although with a bug.
The bug occurs when a User tries to make two files in one run, the program will stop and send me this error message: Exception thrown at 0x00007FF623F51ED9 in To do list.exe: 0xC0000005: Access violation writing location 0x0000000000000008.
The error is pinpointed at this line
(*fileArray)[*size] = _strdup(fileName);
If I close the terminal and press continue, it works again, but it will still happen after the User tries to create 2 files in one run.
The second file does get created in the desired directory but it doesn't get an index position in "index_data.txt", this happens to every file that gets the error after getting created.
If you want to recreate the bug just replace my directory with yours and run the program, after running choose 1 and type a name like "list0" afterwards enter and press A to return to choices again, press 1 and write a name like "list1" after pressing enter the bug should happen
#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;
}
}
I tried to name the files like: file0, file1, list242, listnew, exp12 etc.. it doesn't change anything. I tried naming the file: list 1, the file gets created but the program exits afterwards. I tried removing the created files and keeping the index_data.txt, but the same bug occurs. Tried using the debugger, to understand where the problem lays, didn't get me anywhere.
My friend codes mainly in C++ and knows a little about C, so he is unfortunately clueless about the problem.
Chatgpt keeps saying it's a memory allocation problem and keeps rewriting the code but it never helped. I read the code a couple of times and I am not really sure how to solve it.
struct fileArray { char **strings; size_t size; size_t capacity; }. Then your functions can pass them around by pointer if need be, and you can avoid "three star programming".