Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exists a way to free memory in atexit or similar without using global variables?

I am developing a project in C, and I need to free the allocated memory and also close all the open files before it exits.

I decided to implement a clean function that will do all this stuff and call it with atexit because there are a lot of possible exit scenarios.

The problem is that atexit doesn't allow me to set functions with parameters, so I can't send to clean the pointers that need to be freed in the end of the process.

So I need to declare as global variables every pointer that may need to be freed, and every file that may remaining open in the program? (I already did that but doesn't looks good) or does exist a similar function to atexit that allows to send parameters? or more probably there is another way that I am missing?

like image 538
sir psycho sexy Avatar asked Jul 24 '14 09:07

sir psycho sexy


People also ask

Can you free global variables?

Due to this, global variables are one way we have of sharing the same data between functions. The main difference with local variables is that the memory allocated for variables is freed once the function ends. Global variables are only freed when the program ends.

How is memory allocated differently for a local variable and a global variable?

I have learnt that memory for global variables are allocated at program startup whereas memory for local variables are allocated whenever function call is made.

Where are global variables in memory?

Global variables are stored in the data section. Unlike the stack, the data region does not grow or shrink — storage space for globals persists for the entire run of the program. Finally, the heap portion of memory is the part of a program's address space associated with dynamic memory allocation.

Do global variables waste memory?

It is seldom advisable to use Global variables as they are liable to cause bugs, waste memory and can be hard to follow when tracing code. If you declare a global variable it will continue to use memory whilst a program is running even if you no longer need/use it.


2 Answers

Using a static pointer inside a function:

#include <stdio.h>
#include <stdlib.h>

void atexit_clean(void *data);

static void clean(void)
{
    atexit_clean(NULL);
}

void atexit_clean(void *data)
{
    static void *x;

    if (data) {
        x = data;
        atexit(clean);
    } else {
        free(x);
    }
}

int main(void)
{
    int *a = malloc(sizeof(int));

    atexit_clean(a);
    return 0;
}

Another method using a single global variable: you can store all objects to be freed in an array of pointers or a linked list, this example uses realloc (doesn't check (m/re)alloc for brevity):

#include <stdio.h>
#include <stdlib.h>

static void **vclean;
static size_t nclean;

void atexit_add(void *data)
{
    vclean = realloc(vclean, sizeof(void *) * (nclean + 1));
    vclean[nclean++] = data;
}

void clean(void)
{
    size_t i;

    for (i = 0; i < nclean; i++) {
        free(vclean[i]);
    }
    free(vclean);
}

int main(void)
{
    int *a, *b, *c;
    double *d;
    int e = 1;

    atexit(clean);
    a = &e;
    b = malloc(sizeof(int));
    atexit_add(b);
    c = malloc(sizeof(int));
    atexit_add(c);
    d = malloc(sizeof(double));
    atexit_add(d);
    return 0;
}
like image 166
David Ranieri Avatar answered Nov 14 '22 21:11

David Ranieri


There is no way to pass any parameters to atexit(), so you're stuck using global variables.

When your program terminates normally, through exit() or by returning from main(), it will automatically flush and close any open streams and (under most operating systems) free allocated memory. However, it is good practice to explicitly clean up your resources before the program terminates, because it typically leads to a more structured program. Sometimes the cleanest way to write your program is to just exit and leave the cleanup to the implementation.

But be warned that you should always check the return value of fclose(). See "What are the reasons to check for error on close()?" for an anecdote about what could happen when you don't.

like image 32
Nisse Engström Avatar answered Nov 14 '22 22:11

Nisse Engström