2

I've written this C code. In the beginning, I used file handing to read a text file and insert every line as a string in a linked list. I need to free all cases of memory allocation in the program in a separate void function. How do I do that? I only included the parts of the code that are relevant because it's a pretty long program.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <ctype.h>



/*Node of linked list*/
typedef struct node {
    char *data;
    struct node *next;
} node;

node *start = NULL;
node *current;

typedef enum {
    not_tested, found, missed
} state;

/*Appending nodes to linked list*/
void add(char *line) {

    node *temp = (node *)malloc(sizeof(node));
    temp->data = strdup(line);
    temp->next = NULL;
    current = start;

    if (start == NULL) {
        start = temp;
    }
    else {
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = temp;
    }
}

/*read text file*/
void readfile(char *filename) {
    FILE *file = fopen(filename, "r");

    if (file == NULL) {
        exit(1);
    }

    char buffer[512];

    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        add(buffer);
    }

    fclose(file);
}
OmarAbzd
  • 19
  • 4
  • 3
    `while(start) { node *p = start; start = start->next; free(p->data); free(p); }` - that, assuming you actually ever use these functions, which we don't even know since you don't seem to have a `main`. – WhozCraig Dec 16 '20 at 12:13
  • As I said, I left out the rest of the code because the actual program is over two hundred lines and these functions only really serve one purpose which is to build the linked list. After that, they remain untouched. – OmarAbzd Dec 16 '20 at 13:08

1 Answers1

0

This is not exactly what you're asking for, but I show you how to build a little class that allocates chunks of memory that can bee freed in a single call. This is especially useful when you have lots of small pieces of memory to allocate and therefore to free after usage.

It could seem too many codes for your usage, but note that such a class can be saved in a independent file and reused each time it's needed :

struct Allocator {
    void * buffer;
    size_t capacity;
    size_t usedSize;
};

struct Allocator * newAllocator(size_t initialSize) {
    struct Allocator * allocator = malloc(sizeof(*allocator));
    if (! allocator) return NULL;
    allocator->buffer = malloc(initialSize);
    if (! allocator->buffer) { free(allocator); return NULL; }
    allocator->capacity = initialSize;
    allocator->usedSize = 0;
    return allocator;
}

void freeAllocator(struct Allocator * allocator) {
    if (!allocator) return;
    if (allocator->buffer) free(allocator->buffer);
    free(allocator);
}

void * allocate(struct Allocator * allocator, size_t size) {
    if (size + allocator->usedSize > allocator->capacity) {
        while (size + allocator->usedSize > allocator->capacity) allocator->capacity *= 2;
        allocator->buffer = realloc(allocator->buffer, allocator->capacity);
    }
    void * ptr = allocator->buffer + allocator->usedSize;
    allocator->usedSize += size;
    return ptr;
}
//-------- END ALLOCATOR

struct node {
    //...
};

// How to replace a call to malloc to allocate a node :
void add(struct Allocator *allocator, char *line) {
     struct node *temp = allocate(allocator, sizeof(*temp));
    //...
}

int main()
{
    FILE *file = fopen("myfileName", "r");
    if (file == NULL) exit(1);
    
    // Allocates the buffer and as many nodes as needed 
    struct Allocator *allocator = newAllocator(1024);
    char * buffer = allocate(allocator, 512);
    while (fgets(buffer, 512, file) != NULL) {
        add(allocator, buffer);
    }
    // Free all allocated memory in a single call
    freeAllocator(allocator);
    return 0;
}
dspr
  • 2,383
  • 2
  • 15
  • 19
  • 1
    I'm kind of a beginner and this seems a bit too convoluted (if not to implement, at least to understand). I really only have a couple of terms that I allocated memory for, so I think it would be better to keep it simple, stupid. However, I greatly appreciate the time and effort you took to give this answer. – OmarAbzd Dec 16 '20 at 14:20
  • No problem. As said in comments, to do it in a more classical way, you just need to loop through your nodes and free each of them like this : `free(node)`. – dspr Dec 16 '20 at 14:56