If we were to use malloc() in main(), we could free() that dynamic memory allocation in main().
However, if we use malloc() in a different function
and we use that function in main(), where should we call free() to release the memory allocated in that function?
I.e., in the following source code:
#include <stdio.h>
#include <stdlib.h>
int * memory_allocate_function(int);
int main(void) {
int n=5; //length of array, 5 for example.
int *my_array;
my_array = memory_allocate_function(n);
return 0;
}
int * memory_allocate_function(int n) {
int i;
int *array;
array=(int *)malloc(n * sizeof(int));
if(array == NULL) {
printf("can not allocate memory.");
return NULL;
}
// I think i can't use "free(array);" in here.
// Because I need that array in main().
return array;
}
Is this the best way to do this?
Well after you are done working with it - free the dynamically allocated memory. But design wise - you can call the free in other function also to manage it properly. It really depends. There is no hard rule for that.
For example here you should return that pointer to allocated memory and then after using it in main you can free it in main().
So the structure would be something like
int* memory_allocate_function(int n)
{
int i;
int *array;
array = malloc(n*sizeof(int));
if(array == NULL)
{
printf("can not allocate memory.");
exit(0);
}
return array;
}
Then in main()
int main(void)
{
int n=5; //length of array, 5 for example.
int *arr = memory_allocate_function(n);
// work with arr
free(arr);
return 0;
}
But yes name the function properly - if you are going to use the name memory_allocate_function function then do that only - not any other major logic should be there. This helps create a good readable code.
Note one thing - here when you called the function and then you exited the function the only local variable that contains address of it, it's storage duration ended and you can never then access the memory you allocated. This is a case of memory leak. If you are determined that you won't return the pointer to memory from the function - then work with it (in the same function or different) and then free it (Before the scope of the function ends - notice not mentioning about where you would free it, you can do it in the same function and other function also).
I can't help mentioning few things:- 1) Dont cast the return value of malloc. 2) Check the return value of malloc - in case it is NULL you would like to handle it separately. 3) The recommended signature of main() is int main(void)
Memory should be freed when it's no longer needed.
Since the array would no longer be accessible after memory_allocate_function exits (since the array isn't returned or otherwise made accessible to the outside), it should be freed before memory_allocate_function exits.
void memory_allocate_function(int n){
int i;
int *array;
array = malloc(n*sizeof(int));
if (array == NULL) {
fprintf(stderr, "Out of memory.");
exit(1);
}
// ... use the array ...
free(array);
}
If you need to malloc memory in one function and free in another, you have to somehow carefully pass the pointer to that malloced memory from the point of malloc to the point where you want to free it.
This is your responsibility to preserve the pointer value and hand it from one function to another until it reaches the point of free. If you lose that value along the way, you'll have a memory leak. A memory leak is what you have now, since you are not passing that local array pointer anywhere.
There's no "one true way" to do it, since it depends on your specific intent. For example, you can return that pointer from memory_allocate_function, receive it main and eventually free it there
int *memory_allocate_function(int);
int main()
{
int n = 5;
int *arr = memory_allocate_function(n);
...
free(arr);
return 0;
}
int *memory_allocate_function(int n)
{
int *array = malloc(n * sizeof *array);
...
return array;
}
Related
Building on what I learned here: Manipulating dynamic array through functions in C.
void test(int data[])
{
data[0] = 1;
}
int main(void)
{
int *data = malloc(4 * sizeof *data);
test(data);
return 0;
}
This works fine. However, I am also trying to using realloc in a function.
void increase(int data[])
{
data = realloc(data, 5 * sizeof *data);
}
This complies but the program crashes when run.
Question
How should I be using realloc in a function?
I understand that I should assign the result of realloc to a variable and check if it is NULL first. This is just a simplified example.
You want to modify the value of an int* (your array) so need to pass a pointer to it into your increase function:
void increase(int** data)
{
*data = realloc(*data, 5 * sizeof int);
}
Calling code would then look like:
int *data = malloc(4 * sizeof *data);
/* do stuff with data */
increase(&data);
/* more stuff */
free(data);
Keep in mind the difference between a pointer and an array.
An array is a chuck of memory in the stack, and that's all.If you have an array:
int arr[100];
Then arr is an address of memory, but also &arr is an adress of memory, and that address of memory is constant, not stored in any location.So you cannot say arr=NULL, since arr is not a variable that points to something.It's just a symbolic address: the address of where the array starts.Instead a pointer has it's own memory and can point to memory addresses.
It's enough that you change int[] to int*.
Also, variables are passed by copy so you need to pass an int** to the function.
About how using realloc, all the didactic examples include this:
Use realloc;
Check if it's NULL.In this case use perror and exit the program;
If it's not NULL use the memory allocated;
Free the memory when you don't need it anymore.
So that would be a nice example:
int* chuck= (int*) realloc (NULL, 10*sizeof(int)); // Acts like malloc,
// casting is optional but I'd suggest it for readability
assert(chuck);
for(unsigned int i=0; i<10; i++)
{
chunk[i]=i*10;
printf("%d",chunk[i]);
}
free(chunk);
Both code are very problematic, if you use the same pointer to send and receive from realloc, if it fails, you will lose your pointer to free it later.
you should do some thing like this :
{
...
...
more = realloc(area , size);
if( more == NULL )
free(area);
else
area=more;
...
...
}
I want to declare a global variable inside a main() function...
Below is what I want the program to act like
#include<stdio.h>
int a[6];
int main()
{
int n;
scanf("%d",&n);
}
I want to create an array of user given size (here n-size) and I want to access that array globally.
So instead of creating array of size '6' outside the main() function, I want to create array of 'n' size globally instead of passing array whenever function is called...
You can declare a pointer as global variable and assign buffer to that in main().
#include<stdio.h>
#include<stdlib.h>
int *a;
int main()
{
int n;
scanf("%d",&n);
a = calloc(n, sizeof(*a)); /* calloc() initializes the allocated buffer to zero */
if (a == NULL)
{
/* calloc() failed, handle error (print error message, exit program, etc.) */
}
}
You may want to use an array allocated into the heap by using malloc
#include<stdio.h>
int *a;
int main()
{
int n;
scanf("%d", &n);
a = malloc(sizeof(*a) * n);
if(a == NULL) {
// malloc error
}
// use your array here
free(a); // at the end of the program make sure to release the memory allocated before
}
You cannot do that.
The closest you can get it, define a pointer in file scope (i.e., global), allocate memory to it by using allocator function (malloc() and family) and use the same pointer in other function calls as necessary. As the lifetime of the allocated memory is until deallocated programmatically (passed to free()), other functions can make use of the allocated memory.
I'm working on a C project (assignment for school). One of the demands is that in case of malloc() failure, the program must free() all allocated memory and exit().
Consider a case where function A() constructs a linked-list and in each iteration it calls to another function, B(). Now, if a malloc failure occured at B(), it must free() the memory it allocated but function A() should do that as well.
Things are getting quite complicated when you have a tree of function calls larger than two.
In my previous project I used a flag to notify a malloc() failure - if a function uses another function which may use malloc(), it has to check the flag right after. It worked, but code got kinda messy.
Is there a neat solution for this problem?
Of course, with "real" applications all memory is de-allocated by the OS, but I guess this demand is pedagogical..
I think the easiest approach is to create a custom allocator (as somebody already noted in a deleted post) to keep track of all your allocations, then do a custom deallocator, use these for all your heap memory needs.
if a malloc fails you have the list of previously allocated blocks at easy reach.
e.g.
(you need to redo this cause it is not effective and should be optimized but shows the principle and only ocular compilation)
typedef struct
{
void* pMemory; /* for the allocated memory */
size_t size; /* for better debugging */
} MemoryBlock;
#define MAXBLOCKS 1000
MemoryBlock myheap[MAXBLOCKS]; // global so zero:ed
static int block = 0;
void* myalloc(size_t size)
{
static int block = 0;
// you should check vs MAXBLOCKS
myheap[block].pMemory = malloc(size);
myheap[block].size = size;
// check if it failed.
if ( myheap[block].pMemory == NULL )
{
for (int i = 0; i < block; ++i)
{
myfree(myheap[i].pMemory);
}
fprintf( stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
else
{
return myheap[block++].pMemory;
}
}
void myfree(void* p)
{
for (int i = 0; i < block; ++i)
{
if ( p == myheap[i].pMemory )
{
free(myheap[i].pMemory);
myheap[i].pMemory = NULL;
return;
}
}
}
Yes. The best (and conventional) way is to initialize every pointer value to zero. Then set it during the malloc() assignment. Ex: myPtr = malloc( 10 );
It will be zero in case of failure, and you check that. And finally, when you go about freeing, you always check the pointer value before calling free():
if ( myPtr != 0 )
free( myPtr );
There is no need for an extra flag.
Are you having issue checking for errors or handling them? If you want info on catching them, use donjuedo's suggestion.
For ideas on freeing memory in the event of error, try one of these two methods:
1) For a uni-directional linked-list, keep a special pointer that points to the head of the list. In your cascading free function, start at the head, capture the next-pointer in a temp variable, free the head, move to the next structure in the list using the temp-pointer, and repeat the process until the next-pointer == 0.
2) For a bi-directional linked-list (my preference) you don't need to keep a special pointer to the head of the list. Assuming you are still at the tail, just capture the previous-pointer into a temp variable, free the tail, move back using the temp-pointer, and repeat the process until the previous-pointer == 0
You could look into the atexit() function, to register code that will be executed when the program terminates. Such code can then check if there is anything that needs to be free()d.
Note that atexit() has no way to unregister. So you need to make sure that you register each cleanup function only once, and that it does the right thing when there is nothing to clean up.
#include <stdlib.h>
#include <stdio.h>
int *ptr1;
char *ptr2;
int clean1_registered, clean2_registered;
void clean1(void)
{
printf("clean1 called\n");
if (ptr1) {
free(ptr1);
ptr1 = NULL;
}
}
void clean2(void)
{
printf("clean2 called\n");
if (ptr2) {
free(ptr2);
ptr2 = NULL;
}
}
void B(void)
{
ptr2 = malloc(100);
if (!clean2_registered) {
atexit(clean2);
}
}
void A(void)
{
ptr1 = malloc(100 * sizeof(int));
if (!clean1_registered) {
atexit(clean1);
}
B();
}
int main(int argc, char **argv)
{
A();
}
I am trying to create a function that allocates memory of a certain specified size. In the main, I create the pointer and then send the pointer and the size to the function for memory to be allocated. For some reason it causes all sorts of problems. My program works smoothly if I use the malloc in the main, but not through the function.
int main(void){
int * pointer;
int array_size = SIZE;
...
allocate_memory(&pointer,array_size);
...
free(pointer);
}
allocate_memory(int *pointer,int size){
*pointer = (int *)malloc(size*sizeof(int));
if(!(*pointer)){
printf("Memory allocation fail!");
exit(0);
}
The problem now is that it gives me an error when I try to free the memory.
I would appreciate it if the solution will come with a short explanation. I am starting to be very confused about how these pointers and castings are working.
Thanks in advance!
There were many errors in your program which I am pointing out:
You need to #define the macro SIZE as otherwise the program just won't know what it is.
It's better to declare a prototype of the function allocate_memory() so that any discrepancy in type of arguments or return type is detected
You had passed &pointer as an argument to allocate_array() in main().For this it is necessary to define the function as allocate_memory(int **pointer,int size) instead of allocate_memory(int *pointer,int size) which you have done.
if(*pointer==NULL) implements the condition in a much simpler way and serves just the same purpose.
Use exit(1) for unsuccessful termination as exit(0) is used to denote successful termination.
Never ignore warnings.It's not a good practice.
Here's the corrected code.It compiles well without warnings and does the job (memory allocation) as intended.
#include<stdio.h>
#include<stdlib.h>
#define SIZE 30
void allocate_memory(int**,int);
int main(void){
int * pointer;
int array_size = SIZE;
allocate_memory(&pointer,array_size);
free(pointer);
}
void allocate_memory(int **pointer,int size)
{
*pointer = malloc(size*sizeof(int));
if(*pointer==NULL)
{
printf("Memory allocation fail!");
exit(1);
}
else
printf("\nMemory allocation successful");
}
Building on what I learned here: Manipulating dynamic array through functions in C.
void test(int data[])
{
data[0] = 1;
}
int main(void)
{
int *data = malloc(4 * sizeof *data);
test(data);
return 0;
}
This works fine. However, I am also trying to using realloc in a function.
void increase(int data[])
{
data = realloc(data, 5 * sizeof *data);
}
This complies but the program crashes when run.
Question
How should I be using realloc in a function?
I understand that I should assign the result of realloc to a variable and check if it is NULL first. This is just a simplified example.
You want to modify the value of an int* (your array) so need to pass a pointer to it into your increase function:
void increase(int** data)
{
*data = realloc(*data, 5 * sizeof int);
}
Calling code would then look like:
int *data = malloc(4 * sizeof *data);
/* do stuff with data */
increase(&data);
/* more stuff */
free(data);
Keep in mind the difference between a pointer and an array.
An array is a chuck of memory in the stack, and that's all.If you have an array:
int arr[100];
Then arr is an address of memory, but also &arr is an adress of memory, and that address of memory is constant, not stored in any location.So you cannot say arr=NULL, since arr is not a variable that points to something.It's just a symbolic address: the address of where the array starts.Instead a pointer has it's own memory and can point to memory addresses.
It's enough that you change int[] to int*.
Also, variables are passed by copy so you need to pass an int** to the function.
About how using realloc, all the didactic examples include this:
Use realloc;
Check if it's NULL.In this case use perror and exit the program;
If it's not NULL use the memory allocated;
Free the memory when you don't need it anymore.
So that would be a nice example:
int* chuck= (int*) realloc (NULL, 10*sizeof(int)); // Acts like malloc,
// casting is optional but I'd suggest it for readability
assert(chuck);
for(unsigned int i=0; i<10; i++)
{
chunk[i]=i*10;
printf("%d",chunk[i]);
}
free(chunk);
Both code are very problematic, if you use the same pointer to send and receive from realloc, if it fails, you will lose your pointer to free it later.
you should do some thing like this :
{
...
...
more = realloc(area , size);
if( more == NULL )
free(area);
else
area=more;
...
...
}