Does C reuse memory after reassignment? - c

I'm writing a C program to calculate the path of a particle (similar to the three body problem). In my code I have typedef'ed structs to represent the particle, and a set of vectors to represent the particle's velocity, acceleration and position. As this is an iterative solution I have to recalculate all of these (and consequently malloc a new vector) thousands of times and reassign them to the parent struct in each iteration, like so:
while(collisionCheck(particle, mass0, mass1) == 0)
{
particle-> velocity = recalculateVelocity(particle);
}
I'm concerned about how C will handle the orphaned struct, should I be freeing the old struct like this?
while(collisionCheck(particle, mass0, mass1) == 0)
{
free(particle-> velocity);
particle-> velocity = recalculateVelocity(particle);
}
Or will C garbage collect the orphans and reuse the memory space automatically?

Well … C does not have any garbage collection.
For every memory region that you malloc, you're responsible for free:ing it, yourself.
However, once the memory has been freed, it will generally be re-used.

Only free particle->velocity if it's a pointer and recalculateVelocity() actually creates a new struct (or whatever) and returns the pointer to it.
If you're not using malloc(), you must not use free(). If you've used malloc(), you have to use free(). Only exception here is realloc().

C is not garbage collected, so it will not garbage collect anything. In order to free memory you must use the free() function after you've allocated with malloc().
So the answer is, if particle->velocity is the only pointer to space you've previously allocated with malloc(), you must release the memory with free() before you assign to that pointer, as that will mean you no longer have any pointer to that space, and that is a memory leak.

Related

Does malloc() reuse the same memory address in loop?

I'm starting to learn C programming and stumbled upon a situation that shows my lack of understanding of how memory allocation with malloc() works.
In a loop like the following:
// will only know `xlen` at runtime so I guess I have to use malloc here
char *x = malloc((xlen + 1) * sizeof(*x));
assert(x != NULL); // memory allocation failed
while (fgets(line, sizeof(line), fp) != NULL) {
strncpy(x, line, xlen); // copy first xlen characters of line
x[xlen] = '\0'; // ensure null terminating string
// do something with x
// x can now be "reused" for another line/loop iteration
// free(x) - errors out with "pointer being freed was not allocated"
}
fclose(fp)
free(x);
If the statement free(x) is called inside the loop then when I run this program I get an error message something like a.out(37575,0x7fff964ce3c0) malloc: *** error for object 0x7fab47c02630: pointer being freed was not allocated.
Why am I seeing this error message and what is causing it?
Will the memory address block of x be "re-used" at each iteration of the loop? (I'd say yes, and that would actually be what I wanted in this case) In this case, is it safe to only free the allocated memory of x outside the scope of the loop?
free(x); frees the memory allocated by char *x = malloc(.... It frees all of the memory, and you don't have to worry about how much memory that was, as it keeps track of that. You just have to call free(x); once as you correctly do. This is why you get the error if you free it inside the loop.
Does it mean that the memory address block of x will be "re-used" at
each iteration? (I'd say yes, and that would actually be what I wanted
in this case)
Yes, you use the same memory. It overwrites the memory every time.
In this case, is it safe to only free the allocated memory of x
outside the loop scope?
Yes, you have to free it outside of the loop. Because if you free it, then all of it is freed. If you did that inside the loop, then it would be undefined behavior to keep accessing that memory in following loop iterations.
The malloc() function provides a pointer to an area of memory that can then be used just like any pointer to a memory location.
The way to think of malloc() and free() is to consider it in terms of who owns a memory area. The malloc() function owns the memory that it is managing. When you call the malloc() function, or calloc() function, the function takes some of the memory it is managing and transfers ownership to you. When the function is called and the memory allocated there is a transfer of ownership from the memory management system of malloc() to you and at that point you own that memory and it is up to you to manage it. When the free() function is called to release the memory, you are transferring ownership of the memory area from you back to the memory management system of malloc().
Whenever a transfer of ownership is done, the entity that is giving up ownership is not supposed to do anything further with the memory area since it no longer owns it.
So when you do the malloc() you now own the memory and can use and reuse the memory area as much or as little as you want until such time that you call the free() function to give it back to malloc().
A pointer to a memory region given by malloc() is like any other pointer so far as using it is concerned.
Once you have transferred ownership of a memory area back to malloc() by using thee free() function, you can't call free() again with the same pointer without introducing an error. Once a memory area has been returned using free() you no longer have ownership of the memory so you shouldn't try to do anything else with it and that includes calling free() with the pointer again.
How malloc() manages memory is an implementation detail that will vary depending on the compiler and the C Runtime used. In some cases if you malloc() memory then free() the memory and then malloc() the same amount of memory again you may get lucky and get the same memory area again however it is not something you can count on or should expect.
malloc() provides you a pointer to a memory area that has a couple of guarantees. First of all the memory area provided will be at least as large as you requested. It may be larger but it won't be smaller than what you requested. Secondly the address provided will be on a memory boundary suitable for the machine architecture so that you can use the address provided for any variable type whether a built in such as int or double or a struct or an array of some type.
As the owner of the memory area provided by malloc() you are responsible for giving the memory area back to the malloc() functionality once you are done with it.
Your other primary responsibility is to respect the size of the memory area and to not write a larger data block into the area than the size requested when the malloc() was done. You are guaranteed only the amount of memory requested and writing a larger block of data into the memory will probably overwrite memory that you do not own but is owned by something else.
Unfortunately because the malloc() functionality, at least the optimized or non-debug version of the library, is designed with little as possible overhead, the functionality has few consistency and sanity checks in place. The malloc() functionality trusts that you will obey the rules and guidelines and only use what you own. And often when you break the rules and guidelines, you won't see the effect at the point where you have made a mistake but rather at some other point when some mysterious memory corruption is discovered and your program crashes.
You can use and reuse dynamically allocated memory as long as you have not called free() on it. If you free it and attempt to use it again, then you will have undefined behaviour.
You can continue to reusing memory (eg buf created by char *buf = calloc(sizeOfBuf); ) allocated to you on a single call to calloc(), until free(buf) is called, just as if buf was created statically, eg char buf[sizeOfBuf]; = 0. However, if the size of the buffer initially created by using calloc() needs to change, realloc() is available to do this, and is the preferable method. There are some caveats about using realloc however. Here is an example of using realloc, this one packaged into a function that resizes an existing dynamically allocated buffer, and takes care of some of the caveats:
realloc usage example:
// initial call to calloc
char *buf = calloc(sizeOfBuf);
if(buf)
{
while(someConditionIsTrue)
{
// read new content
//...
//new content needs to be added to buf
char *tmp = realloc(buf, newSizeOfBuffer);
if(!tmp)//if failed...
{
free(buf);//... free original buf to prevent memory loss
return NULL;// return null, caller must test for this
}
buf = tmp;//...else copy new mem location back to original pointer
//continue doing stuff with buf
}
//when done with buf, free it
free(buf);
}
One other suggestion, consider calloc() returns uninitialized memory, i.e. you own a space that contains whatever was occupying it when it was given to you. It is a good idea to follow that command with a method to clean up the buffer:
memset(buf, 0, sizeOfBuf);
Or use calloc().

Allocating array on heap in C

I'm allocating an array of of "Todo" structs on the heap like so:
struct Todo *todos = malloc(n * sizeof(*todos));
My understanding is that I have now allocated memory for all of my n Todo structs. So if I want to save some values I can just do for example:
todos[i].id = 1;
The problem now is that if I try to free that memory using free(&todos[i]); I get an error telling me that I haven't allocated that pointer.
My question is now, do I just need to free the todos array and not every element on its own?
You have allocated one single block of memory for all your Todo structures. You can not free a single element. Just like you should not free elements of a non-heap allocated array.
Each call to malloc (or calloc) should be matched by a single call to free.
A little bit of background to Some programmer dude's answer
C11 standard, 7.22.3.3 "The free function", paragraph 2:
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
[emphasis by me]
Background (second level...) is that typically, you did not only receive the memory starting at the pointer, but additionally there is some kind of (machine/OS specific) control block right before the pointer's address that is needed to free the memory again.
You might try to peek at this control block by reading some bytes right before the pointer (just out of curiosity), but be aware that this actually is undefined behaviour as well (so don't ever do this in production code!) and might lead to your programme crashing.
As a reference, always that you do:
WhateverTypeInTheWorld *var1 = malloc(whateveryouwanttocompletearray);
then, you have to do
free(var1); /* use the same value you received from malloc() */
to return the memory back... as you did only one malloc(), you can do only one free() and pass to it the same pointer you got from malloc().
When you write:
free(&todos[i].i);
you are passing free the i-esim element field i's address, and not the pointer you received from malloc(). Probably you understood that you can free part of the memory you received... but it doesn't work that way... you get the memory in chunks, and you have to return it in those same chunks you received from malloc.

Calloc(), Structs & C

So I'm new to C and creating some simple programs to help me get a hang of things.
Let's say I have a struct as follows:
typedef struct {
char* field;
} something;
And I dynamically allocate space for 10 of these as follows:
something* stuff = calloc(10, sizeof(something));
Let's say I then want to delete one of these somethings. Would it make sense to do:
free(&stuff[4]);
Or would that only make sense if I had made all of these pointers to somethings instead of a contiguous block of somethings?
If I did that and it worked, would:
stuff[4] = malloc(sizeof(something))
Then be all I need to re-add a "something" to that index?
Or, in general, do we usually deal with such structures as a block of memory that contains pointers to the structs, not the structs themselves?
Thanks.
The rule is very simple. You can and should free precisely that which you allocated. That is, you must only pass pointers to free() which you received as the return value of malloc/calloc/realloc etc.*, or a null pointer. Nothing else may be passed to free().
So, you can free tne entire array, or nothing at all.
(Note also that "freeing a single element from the middle" would be utterly pointless, because you would have no way of iterating over such a "holy" array sensibly.) If you want to deallocate some memory, allocate a new range, copy the desired elements over and free the original array.
*) Some quasi-standard functions may indirectly return dynamically allocated memory which you must fre; check the documentation. Some examples are strdup, GNU's scanf, and GCC's abi::__cxa_demangle.)
According to the man pages
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs.
You can only free the whole block of data. So do not attempt to free anything else.

Why must malloc be used?

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
}

Freeing portions of dynamically allocated blocks?

I was curious whether there exists a dynamic memory allocation system that allows the programmer to free part of an allocated block.
For example:
char* a = malloc (40);
//b points to the split second half of the block, or to NULL if it's beyond the end
//a points to a area of 10 bytes
b = partial_free (a+10, /*size*/ 10)
Thoughts on why this is wise/unwise/difficult? Ways to do this?
Seems to me like it could be useful.
Thanks!
=====edit=====
after some research, it seems that the bootmem allocator for the linux kernel allows something similar to this operation with the bootmem_free call. So, I'm curious -- why is it that the bootmem allocator allows this, but ANSI C does not?
No there is no such function which allows parital freeing of memory.
You could however use realloc() to resize memory.
From the c standard:
7.22.3.5 The realloc function
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.
There is no ready-made function for this, but doing this isn't impossible. Firstly, there is realloc() . realloc takes a pointer to a block of memory and resizes the allocation to the size specified.
Now, if you have allocated some memory:
char * tmp = malloc(2048);
and you intend to deallocate the first, 1 K of memory, you may do:
tmp = realloc(foo, 2048-1024);
However, the problem in this case is that you cannot be certain that tmp will remain unchanged. Since, the function might just deallocate the entire 2K memory and move it elsewhere.
Now I'm not sure about the exact implementation of realloc, but from what I understand, the code:
myptr = malloc( x - y );
actually mallocs a new memory buffer of size x-y, then it copies the bytes that fit using memcpy and finally frees the original allocated memory.
This may create some potential problems. For example, the new reallocated memory may be located at a different address, so any past pointers you may have may become invalidated. Resulting in undefined runtime errors, segmentation faults and general debugging hell. So I would try to avoid resorting to this.
Firstly, I cannot think of any situation where you would be likely to need such a thing (when there exists realloc to increase/decrease the memory as mentioned in the answers).
I would like to add another thing. In whatever implementations I have seen of the malloc subsystem (which I admit is not a lot), malloc and free are implemented to be dependent on something called as the prefix byte(s). So whatever address is returned to you by malloc, internally the malloc subsystem will allocate some additional byte(s) of memory prior to the address returned to you, to store sanity check information which includes number of allocated bytes and possible what allocation policy you use (if your OS supports multiple mem allocation policies) etc. When you say something like free (x bytes), the malloc subsystem goes back to peek back into the prefix byte to sanity check and only if it finds the prefix in place does the free successfully happen. Therefore, it will not allow you to free some number of blocks starting in between.

Resources