I'm having trouble when I try to use malloc to allocate new space for floats inside my array.
My goal is to dynamically create array, and malloc to add a space for new float each time I want to add a new float.
Here is the code I am trying to run, but each time it only allocates an array with sizeof(float), even though the variables keep increasing.
float *funkcia_e(FILE **subor, int *pocet_cien) {
float *pole_cien;
*pocet_cien = 1;
while (fgets(nazov, sizeof nazov, *subor) != NULL)
{
pole_cien = (float*) malloc((*pocet_cien) * 4);
fscanf(*subor, "%f", &pole_cien[pozicia++]); //This causes problems
*pocet_cien = *pocet_cien + 1;
}
}
int main() {
int pocet_cien = 1;
float *pole_cien = NULL;
funkcia_r(&subor, pole_cien, &pocet_cien);
}
Here is the recorded debugging: https://s.put.re/RR6wqRk.mp4
It appears the malloc actually corrupts the array, instead of exntending it. Any ideas?
You need to use realloc. It does what you wanted malloc to do, i.e. lets you extend a previously allocated block. In contrast, malloc is a one-shot deal: you get your memory block, and that's what you have to work with.
(from the comment) cant afford to realloc, as I have to allocate the array dynamically and realloc would purge the contents of array when reallocating it.
That is not true: when realloc extends the amount of memory allocated to your program, and decides that it must re-allocate the block, it copies the content of the current block into the new block, up to the allocated size of the old block, so the new block is ready to use. Hence, your current program results in a memory leak.
In order to let main use results of allocation you must pass the pointer pole_cien by pointer, i.e. as float**. Otherwise the results of assigning it inside funkcia_e are not propagated to main.
A few other points to consider:
Do not cast malloc results
Do not hard-code size of float as 4; use sizeof(float)
Make sure pocet_cien starts at zero, and use it in place of pozicia; add 1 on the call to realloc.
It is quite obvious as malloc does not "add" any memory, but allocates a new chunk of it - every time fresh. So eventually you access not allocated memory and you get the memory fault as index increments all the time but you allocate the space for 4 elements.
Related
I created array with 10 integer size using malloc. I added values to the elements. Then, I reallocated it to 200 bytes into newArr. And then I reallocated newArr into newArr2 with size of 10 integers again. Code:
void main(){
int i, *arr = (int *)malloc(10* sizeof(int));
for(i=0; i<10; i++){
arr[i] = i;
}
int *newArr = (int *)realloc(arr, 200);
int *newArr2 = (int *)realloc(newArr, 10* sizeof(int));
}
How should I use free to remove all the allocated memory here? I'm getting error while clearing all of them.
Edit: As per the accepted answer the old memory should've been cleared but it didn't. I was able to access memory and was able to change value on old address.
From my point of view, when you use malloc or realloc you're changing the memory reference, so, if you call realloc on a variable you are freeing the old space used and allocate new space, copying the old data to the new memory position, so, in your example, arr doesn't hold a valid memory address after first realloc. The same thing happen on newArr
realloc is basically malloc with the new size, memmove the data to the new block and free the old one. (But implementation can optimize this process because they've got more information they can use, like just extending the current allocated block, producing the same pointer)
So the pointers arr and newArr are invalid and shouldn't be accessed anymore because they might have been freed, so the pointer in newArr2 is the current one and valid, if the previous allocations didn't fail. So free(newArr2) is the correct answer.
Sure, you might access the memory from the old pointers, but it isn't guaranteed because it might've been allocated and overwritten for a different purpose or you might just be lucky to get the same pointer back from realloc (because from eg. the optimization above). It's just undefined behavior when accessing freed memory.
Source on reddit
At the end of the code below, which pointer would I need to plug into free(), array or temp_array? Does it matter which one or would either free the memory block?
int *array = 0;
int *temp_array = 0;
int count = 0;
array = malloc(sizeof(int));
// skipping code where count is calculated...
temp_array = realloc(array, count * sizeof(int));
if (temp_array == NULL) {
free(array);
// some error message
return;
}
array = temp_array;
// skipping section of code, which reads numbers from a file and loads them into an array
// amount of numbers read can be 0 to whatever
free (array); // free array or temp_array?
Also, is it possible to allocate a block of memory with realloc if the pointer it's trying to allocate memory for is NULL (in other words, do I need to allocate memory first with malloc and later resize it with realloc, or can I skip the malloc)?
It doesn't matter - both temp_array and array point to the same memory block. I would prefer temp_array as then the realloc and free pointers match. Depending on your working code, for protection you could consider assigning both pointers to NULL to prevent free-ing the memory twice. free(NULL) is safe - no operation is performed.
Regarding the initial alloc of one integer - is that necessary? From the code shown, an int defined on the stack would be preferable.
EDIT:
After more info from OP (in comments) it appears the code can be simplified using an header value which holds the number of records in the file. This eliminates the need for realloc and permits memory allocation prior to reading the file values in.
I'm in the middle of a project and I'm trying to use malloc() and realloc(). I know when I malloc, it works, but when I use realloc, it doesn't change the amount of alloced memory at all. I've always though that realloc will re-allocate your already malloced memory.
Here is what I have:
This include:
#include <stdlib.h>
I have a struct:
struct student {
int age;
int numOfClasses;
int gender; //0 male; 1 female
} student;
When I want to make 7 of those structs using malloc, I will use this line of code:
student stud* = (structure*) malloc(7*sizeof(student));
This line works. That line of code takes the size of the structure and multiples that by 7. In short, this will grab enough memory to make an array of 7 structures.
Now, if I want to change that to 8, I would do this where A is the previous malloced memory, and B is the new malloced (or realloced) memory:
Here is how I have it in code:
stud = (student*)realloc(stud, 8*sizeof(student));
From what I know, realloc takes the variable in the second parameter and mallocs that amount of memory. Then, it takes the pointer (or previous malloced), and fills in the just malloced memory with as much as it can from the given pointer. Of course, the second parameter must be bigger than the previous malloced size, or stud will lose some memory on the end. Now this is where my problem is. When I call the line above, it doesn't change anything. The malloced array is still length of 7. I'm pretty sure, also, that I have enough memory to realloc.
Am I doing this right? Where could my problem be?
Your understanding of realloc's behaviour is nearly correct. It doesn't have to return a different pointer; it may be that there was enough unused memory after the initial block, so the heap manager can just return the same pointer back to you (but adjust its own internal state such that it knows the block is now bigger).
You have made one small mistake, though.
stud = (student*)realloc(stud, 8*sizeof(student));
Here you are replacing your stud pointer with the return value from realloc. If it happens to return NULL due to memory starvation, then you have lost your original stud pointer and the memory is leaked. You should use a temporary pointer instead.
tmp = realloc(stud, 8*sizeof(student));
if (tmp)
stud = tmp;
Also note that you still have to actually put something in the eighth slot. After the realloc the eighth slot is valid allocated memory, but contains garbage until you store something meaningful in it.
This should work, although I'd have these recommendations:
Don't cast the return from malloc. It's useless in C and may hide that you have forgotten to include <stdlib.h>.
Do not use ptr = realloc (ptr, ...) as this creates a memory leak in the case realloc returns NULL. Instead, use
if ((new_ptr = realloc (stud, 8 * sizeof (*stud))) != NULL) {
stud = new_ptr;
} else {
scream_and_die("out of memory");
}
And use sizeof (*stud), i.e. reference an expression using the pointer, not the type being pointed to (to be independent of the particular type of pointer you allocate). This way, when you rename the typedef, the malloc/realloc line needs no modification. In other words, Best Practice for Dynamic Memory Allocation in C is
#include <stdlib.h>
sometype *ptr;
...
ptr = malloc (N * sizeof *ptr);
for an array of N sometypes.
I know that realloc will free memory when necessary, and I know the third rule of C - "for every malloc there must be an equal and opposite free"... but how do these two work together?
The situation is best described in code:
int main()
{
myStruct **myStructArray;
int i, num_elements;
num_elements = getnumber(); // gets value for num_elements
myStructArray = (myStruct **) malloc(num_elements * sizeof(myStruct*));
for (i=0; i<num_elements; i++)
myStructArray[i] = (myStruct *) malloc(sizeof(myStruct));
// so far so good...
num_elements = getnumber(); // gets new, LOWER value
myStructArray = realloc(myStructArrary, num_elements * sizeof(myStruct*));
// rest_of_code, and necessary free loop for myStructArray etc...
}
Obviously the above is nothing more than a snippet, but a snippet paints a thousand words.
Would this create a memory leak? I know the call to realloc will free the pointers' memory, but I can see arguments for and against the possibility that there is still going to be a bunch of memory forgotten about.
A leak can be circumvented by incorporating int number_elements_new into the code and loop free-ing the surplus myStructs before calling realloc to free the (now NULL) pointers.
If realloc does the donkeywork and frees up ALL the associated memory that's great, otherwise I've got to trawl through to make sure nothing has been missed - myStruct itself contains allocated memory and so on.
Thank you for your recommendations...
malloc, realloc and free have no idea about what the memory is being used for. If you're using the memory to store pointers to other dynamically-allocated memory, then that's for you to tidy up!
Also, note that the way you're using realloc in your code snippet is potentially unsafe. If realloc fails, it leaves the original memory un-freed, and returns NULL. Best practice is to assign the return value to a temporary pointer, and then check. See e.g. http://www.c-faq.com/malloc/realloc.html.
If you're shrinking the size of your array, you would first need to free each myStructArray[i] where i >= num_elements, otherwise you will have a memory leak.
Put another way, shrinking the size of the pointer array does not affect the memory that each array element was pointing to.
Also, in the realloc call, you will want to assign the result to a temporary pointer; if realloc cannot extend or shrink the buffer, it will return NULL, and you'll lose your reference to that block, which will also introduce a leak:
myStruct **tmp = realloc(myStructArray, ...);
if (tmp)
{
myStructArray = tmp;
...
}
If the number is lower than the existing number of elements, you will introduce a memory leak as the reallocated block is not related to the content and you are losing your reference to the blocks allocated in the for-loop.
Therefore you'll have to loop through your array and free all elements that will be subject to removed.
If the number is higher than the existing number, it won't create a memory leak as realloc copies the existing data if a new memory block has been allocated. Therefore your other dynamically allocated blocks (malloc in the for loop) are still referenced by the resized array. The only gotcha here is, that the newly allocated array spaces are uninitialized and can therefore contain invalid pointers.
From what I understand, the malloc function takes a variable and allocates memory as asked. In this case, it will ask the compiler to prepare memory in order to fit the equivalence of twenty double variables. Is my way of understanding it correctly, and why must it be used?
double *q;
q=(double *)malloc(20*sizeof(double));
for (i=0;i<20; i++)
{
*(q+i)= (double) rand();
}
You don't have to use malloc() when:
The size is known at compile time, as in your example.
You are using C99 or C2011 with VLA (variable length array) support.
Note that malloc() allocates memory at runtime, not at compile time. The compiler is only involved to the extent that it ensures the correct function is called; it is malloc() that does the allocation.
Your example mentions 'equivalence of ten integers'. It is very seldom that 20 double occupy the same space as 10 int. Usually, 10 double will occupy the same space as 20 int (when sizeof(int) == 4 and sizeof(double) == 8, which is a very commonly found setting).
It's used to allocate memory at run-time rather than compile-time. So if your data arrays are based on some sort of input from the user, database, file, etc. then malloc must be used once the desired size is known.
The variable q is a pointer, meaning it stores an address in memory. malloc is asking the system to create a section of memory and return the address of that section of memory, which is stored in q. So q points to the starting location of the memory you requested.
Care must be taken not to alter q unintentionally. For instance, if you did:
q = (double *)malloc(20*sizeof(double));
q = (double *)malloc(10*sizeof(double));
you will lose access to the first section of 20 double's and introduce a memory leak.
When you use malloc you are asking the system "Hey, I want this many bytes of memory" and then he will either say "Sorry, I'm all out" or "Ok! Here is an address to the memory you wanted. Don't lose it".
It's generally a good idea to put big datasets in the heap (where malloc gets your memory from) and a pointer to that memory on the stack (where code execution takes place). This becomes more important on embedded platforms where you have limited memory. You have to decide how you want to divvy up the physical memory between the stack and heap. Too much stack and you can't dynamically allocate much memory. Too little stack and you can function call your way right out of it (also known as a stack overflow :P)
As the others said, malloc is used to allocate memory. It is important to note that malloc will allocate memory from the heap, and thus the memory is persistent until it is free'd. Otherwise, without malloc, declaring something like double vals[20] will allocate memory on the stack. When you exit the function, that memory is popped off of the stack.
So for example, say you are in a function and you don't care about the persistence of values. Then the following would be suitable:
void some_function() {
double vals[20];
for(int i = 0; i < 20; i++) {
vals[i] = (double)rand();
}
}
Now if you have some global structure or something that stores data, that has a lifetime longer than that of just the function, then using malloc to allocate that memory from the heap is required (alternatively, you can declare it as a global variable, and the memory will be preallocated for you).
In you example, you could have declared double q[20]; without the malloc and it would work.
malloc is a standard way to get dynamically allocated memory (malloc is often built above low-level memory acquisition primitives like mmap on Linux).
You want to get dynamically allocated memory resources, notably when the size of the allocated thing (here, your q pointer) depends upon runtime parameters (e.g. depends upon input). The bad alternative would be to allocate all statically, but then the static size of your data is a strong built-in limitation, and you don't like that.
Dynamic resource allocation enables you to run the same program on a cheap tablet (with half a gigabyte of RAM) and an expensive super-computer (with terabytes of RAM). You can allocate different size of data.
Don't forget to test the result of malloc; it can fail by returning NULL. At the very least, code:
int* q = malloc (10*sizeof(int));
if (!q) {
perror("q allocation failed");
exit(EXIT_FAILURE);
};
and always initialize malloc-ed memory (you could prefer using calloc which zeroes the allocated memory).
Don't forget to later free the malloc-ed memory. On Linux, learn about using valgrind. Be scared of memory leaks and dangling pointers. Recognize that the liveness of some data is a non-modular property of the entire program. Read about garbage collection!, and consider perhaps using Boehm's conservative garbage collector (by calling GC_malloc instead of malloc).
You use malloc() to allocate memory dynamically in C. (Allocate the memory at the run time)
You use it because sometimes you don't know how much memory you'll use when you write your program.
You don't have to use it when you know thow many elements the array will hold at compile time.
Another important thing to notice that if you want to return an array from a function, you will want to return an array which was not defined inside the function on the stack. Instead, you'll want to dynamically allocate an array (on the heap) and return a pointer to this block:
int *returnArray(int n)
{
int i;
int *arr = (int *)malloc(sizeof(int) * n);
if (arr == NULL)
{
return NULL;
}
//...
//fill the array or manipulate it
//...
return arr; //return the pointer
}