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.
Related
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.
I have many structures, one of which looks like
typedef int Info;
typedef struct
{
Info info;
} Item;
So if I allocate like so:
ItemRef a;
a= malloc(sizeof(ItemRef));
where ItemRef is just typecasted int.
My question is if I deallocate a now, will info inside it also be deallocated?
Because when I tried assigning vale to info in a and then deallocating is and then printing it I was still able to access the value.
So does that mean deallocating a structure does NOT deallocate its components ? Even though I didn't have to individually allocate the components?
Deallocating a struct does deallocate the space for its members. However the rules of the C language do not require that the freed memory is zeroed out or made inaccessible in any way. All freeing does is tell the memory manager that you've finished with that bit of memory and it can reuse it at its discretion.
So, in a typical implementation, if you still have a pointer to the freed memory the compiler won't do anything to stop you accessing it. Doing so puts you in the realm of undefined behaviour which means anything can happen. Messing up in this way and accessing freed memory is a source of annoying and difficult to find bugs in C programs because the behaviour is often not consistent.
From http://opengroup.org/onlinepubs/007908775/xsh/free.html
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 the calloc(), malloc(), realloc()
or valloc() function, or if the space is deallocated by a call to
free() or realloc(), the behaviour is undefined. Any use of a pointer
that refers to freed space causes undefined behaviour.
As per the documentation, the free doesn't initializes all the memory bits, it freed, to any value. Thus the memory (might) still contain the old value. but its undefined behavior to refer it as stated.
The best practice is to::
free(a) ;
a = NULL ;
I have an array of pointers
char *wordlist[9];
and then I malloc() a block of memory on every of this pointers
for(int i=0; i<9; i++)
wordList[i] = (char*)malloc(someLength);
Lets suppose that every time the someLength is different.
And the problem is now, that I want to realloc() ie. 4th elemet of wordList to a larger size than it is now.
wordList[3] = (char*) realloc(&wordList[3], someBiggerSize);
Since malloc allocates a consistent block of memory, is that operation even possible without colliding with wordList[4]?
There's nothing to worry about this in principle. You just have an array of pointers and each element of the array points to a distinct memory block. Each element of the array, each pointer, can be therefore be reallocated independent of the other elements.
Now, I say in principle because your code does have an error. You should pass wordList[3] rather than &wordList[3] to the realloc.
Just remove the & . wordList[3] = (char*) realloc(wordList[3], someBiggerSize);
wordList[3] is a pointer, and realloc expected to get a pointer that allocated by malloc. not pointer to it.
About your last question: every time you call malloc, it return a consistent block of memory. there is not guarantee that memory, allocated by two calls for malloc, will be consistent. In other words, wordList[3] and wordList[4] are not must be consistent, and you can do whatever you want two one of them (as long as you care about the buffers size) without thinking about the other.
Why should it be colliding? You have declared an array of pointers, each of which points to memory that is allocated elsewhere. When you reallocate you are just changing the size/position of this memory, the pointer returned by realloc is as big as it was.
By the way, you shouldn't be using realloc that way, since, if it fails, you'd be leaking memory; see e.g. here.
---edit---
And, as #asaelr noted, you should remove that &, just reallocing the block pointed by wordList[3], not the memory of wordList.
You have a misunderstanding about what realloc does. It will return a whole new block of memory (if the new size is larger than the old size) instead of increasing the size of the block that was passed into it.
malloc allocates a trunk of memory from heap and that trunk of memory can't be allocated for other malloc until you free them. In other words, malloc succeeds only if there are enough continuous free space in the heap. So this makes sure that the memory allocated would not collide with any others in your words.
Each of your pointers points to a separate and independent block of memory. Inside your array of pointers, each element is simply an address and overwriting one won't affect the others. So, what you are doing is fine and won't cause any problems with other elements of the array. As others mentioned, you should be passing wordList[3] and not &wordList[3]
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.
Maybe a bad topic, but given the following code, do i need to free(player->name) too?
#include <stdio.h>
struct Player
{
char *name;
int level;
};
int main()
{
struct Player *player;
player->name = malloc(sizeof(player->name)*256);
player->name = "John";
printf(player->name);
free(player);
printf("\n\n\n");
system("PAUSE");
return 0;
}
Oh boy, where to start? You really need a good book. Sigh. Let's start at the top of main():
This
struct Player *player;
defines a pointer to a struct Player, but it doesn't initialize it. It has thus a more or less random value, pointing somewhere into memory. This
player->name = malloc(sizeof(player->name)*256);
now writes into parts of that random location the address of a piece of memory obtained by malloc(). Writing to memory through an uninitialized pointer invokes Undefined Behavior. After that, all bets are off. No need to look further down your program. You are unlucky that, by accident, you write to a piece of memory that is owned by your process, so it doesn't crash immediately, making you aware of the problem.
There's two ways for you to improve that. Either stick to the pointer and have it point to a piece of memory allocated for a Player object. You could obtain it by calling malloc(sizeof(Player).
Or just use a local, automatic (aka stack-based) object:
struct Player player;
The compiler will generate the code to allocate memory on the stack for it and will release it automatically. This is the easiest, and should certainly be your default.
However, your code has more problems than that.
This
player->name = malloc(sizeof(player->name)*256);
allocates consecutive memory on the heap to store 256 pointers to characters, and assigns the address of the first pointer (the address of a char*, thus a char**) to player->name (a char*). Frankly, I'm surprised that even compiles, but then I'm more used to C++' stricter type enforcement. Anyway, what you probably want instead instead is to allocate memory for 256 characters:
player->name = malloc(sizeof(char)*256);
(Since sizeof(char) is, by definition, 1, you will often see this as malloc(256).)
However, there more to this: Why 256? What if I pass a string 1000 chars long? No, simply allocating space for a longer string is not the way to deal with this, because I could pass it a string longer still. So either 1) fix the maximum string length (just declare Player::name to be a char array of that length, instead of a char*) and enforce this limit in your code, or 2) find out the length needed dynamically, at run-time, and allocate exactly the memory needed (string length plus 1, for the terminating '\0' char).
But it gets worse. This
player->name = "John";
then assigns the address of a string literal to player->name, overriding the address of the memory allocated by malloc() in the only variable you store it in, making you lose and leak the memory.
But strings are no first-class citizens in C, so you cannot assign them. They are arrays of characters, by convention terminated with a '\0'. To copy them, you have to copy them character by character, either in a loop or, preferably, by calling strcpy().
To add insult to injury, you later attempt to free the memory a string literal lives in
free(player);
thereby very likely seriously scrambling the heap manager's data structures. Again, you seem to be unlucky for that to not causing an immediate crash, but the code seemingly working as intended is one of the worst possibilities of Undefined Behavior to manifest itself. If it weren't for all bets being off before, they now thoroughly would be.
I'm sorry if this sounds condemning, it really wasn't meant that way, but you certainly and seriously fucked up this one. To wrap this up:
You need a good C++ book. Right now. Here is a list of good books assembled by C programmers on Stack Overflow. (I'm a C++ programmer by heart, so I won't comment on their judgment, but K&R is certainly a good choice.)
You should initialize all pointers immediately, either with the address of an existing valid object, or with the address of a piece of memory allocated to hold an object of the right type, or with NULL (which you can easily check for later). In particular, you must not attempt to read from or write to a piece of memory that has not been allocated (dynamically on the heap or automatically on the stack) to you.
You need to free() all memory that was obtained by calling malloc() exactly once.
You must not attempt to free() any other memory.
I'm sure there is more to that code, but I'll stop here. And did I mention you need a good C book? Because you do.
You have to free() everything that you malloc() and you must malloc() everything that is not allocated at compile time.
So:
You must malloc player and you must free player->name
Ok, so your variable player is a pointer, which you have not initialized, and therefore points to a random memory location.
You first need to allocate the memory for player the way you have done for player->name, and then alocate for player->name.
Any memory allocated with malloc() needs to be freed with free().
Take a look at this and this.
This is awful code. Why? Firstly you allocate memory for player->name. malloc returns pointer to allocated memory. In next step you lose this pointer value because reassign player->name to point to static "John" string. Maybe you want to use strdup or sprintf functions?
Also the big mistake is to use uninitialized pointer to player struct. Try to imagine that it can point to random memory location. So it is good idea allocate memory for your structure with help of malloc. Or don't use pointer to structure and use real structure variable.
player doesn't need to be freed because it was never malloc'd, it's simply a local stack variable. player->name does need to be freed since it was allocated dynamically.
int main()
{
// Declares local variable which is a pointer to a Player struct
// but doesn't actually point to a Player because it wasn't initialised
struct Player *player;
// Allocates space for name (in an odd way...)
player->name = malloc(sizeof(player->name)*256);
// At this point, player->name is a pointer to a dynamically allocated array of size 256*4
// Replaces the name field of player with a string literal
player->name = "John";
// At this point, the pointer returned by malloc is essentially lost...
printf(player->name);
// ?!?!
free(player);
printf("\n\n\n");
system("PAUSE");
return 0;
}
I guess you wanted to do something like this:
int main() {
struct Player player;
player.name = malloc( 256 );
// Populate the allocated memory somehow...
printf("%s", player.name);
free(player.name);
}