freeing memory inside the pointer of structure - c

I have this structure
typedef struct Rectangle{
char *name;
int size;
}RCG;
typedef struct Shapes{
RCG *rectangle;
}SHP;
Here is the problem of mine I dynamically allocated the RCG with 20 ;
SHP shp;
shp.rectangle = (RCG*)malloc(sizeof(RCG *) * 20)
also allocated memory to the name of rectangle inside the pointer;
shp.rectangle[0].name = malloc(10*sizeof(char));
shp.rectangle[0].name = "big";
how can I free the name??
what i did is
free(shp.rectangle[0].name);
it gives me an error of "the heap may be corrupted"
I use visual studio 2010

When you use the following line
shp.rectangle[0].name = "big";
You are setting the pointer to a different location than the original return value of malloc.
What you probably want instead is the following.
memcpy(shp.rectangle[0].name, "big", strlen("big") + 1)
Also, whether the pointer is inside a structure is not relevant. You would have the same issue even if the pointer was not defined inside a structure.
Update: As mentioned in the comment below, since we dealing with strings in this particular case, it is probably more appropriate to use the function strncpy instead of the more general memcpy.
strncpy(shp.rectangle[0].name, "big", 10*sizeof(char))
Note that 10*sizeof(char) is hardcoded above because that is the size of the earlier malloc.

This: shp.rectangle[0].name = "big"; does not copy the chars into the allocated space but assigns the address of the string "big" to the pointer name. The allocated memory is not referenced any longer anywhere so you lost any way of freeing it. Instead you try to free the string "big" which is part of your executable, actually.
memcpy or even better strcpy is commonly used for copying strings; those will assign to each char in name the corresponding value in "big".

Related

How to free() an array of structs allocated by malloc()?

I've been working on a project that uses structs as storage for strings. I declared a struct consists of char type members:
struct datastore1
{
char name[50];
char address[50];
char email[50];
char number[50];
char idnum[50];
};
I'm aware that I can just do char *name, char *address... but let's say we specified it with max length of 50. Then on my function which uses the struct, I malloc'ed it with index size of 30:
struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));
Supposedly I finished copying all strings into the struct by accessing each index, How should i free the allocated memory that was used after calling malloc? I tried doing free(dsdata) on the end of the program but I am not sure if it's the right way. Should i free each indexes individually? Please enlighten me. Thank you in advance for the feedback!
How should i free the allocated memory that was used after calling malloc?
Consider below example,
struct datastore1 *obj1 = malloc(sizeof(struct datastore1));
free(obj1);
Here obj1 is pointing to the block of memory of size same as size of datastore1 in order to free you need to send the address which is allocated by malloc.
likewise,
struct datastore1 *obj2 = malloc(3 * sizeof(struct datastore1));
free(obj2);
obj2 is pointing to a block of contiguous memory of size 3 * sizeof(datastore1) you need to pass the base address to free
Should i free each indexes individually?
NO, Since block of memory is allocated only once and you need to free exactly one time.
Let me extend it further,
struct datastore1 *obj3[3];
for(int i=0;i<3;i++)
obj3[i] = malloc(sizeof(struct datastore1));
for(int i=0;i<3;i++)
free(obj3[i]);
Here obj3 is array of pointer and each index is pointing to different part of memory and hence need to be freed individually.
Note: For simplicity I haven't considered return value from malloc. Null check has to be done on malloc return value.
1.
How should I free the allocated memory that was used after calling malloc?
I tried doing free(dsdata) on the end of the program but I am not sure if it's the right way.
free(dsdata) is fine, since you allocated the whole space by just one call to malloc with:
struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));
To cite the standard (C18), 7.22.3.4 - "The malloc function" (emphasize mine):
7.22.3.4 The malloc function
Synopsis
1
#include <stdlib.h>
void* malloc(size_t size);
Description
2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
Returns
3 The malloc function returns either a null pointer or a pointer to the allocated space.
It is correct to use free(dsdata) because malloc allocated all of the required space at once and returned a pointer to the first structure variable of this array which is assigned to the pointer of dsdata.
The free() function "knows" that dsdata is a reference to the whole allocated space. You do not need to free each of the 30 structures of type struct datastore1 in memory individually.
2.
Should I free each indexes individually?
No, you do not need and even more important you should not do so; this would be Undefined Behavior:
Citation from the current standard (C18), 7.22.3.5/3 - "The free function" (emphasize mine):
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.
As far as I understand you only used malloc to allocate space for an array of datastore1 struct, so it is sufficient to just do free(dsdata).
If in the struct you would have pointers and you would use malloc to allocate each of them, only than you would need to free each of them first.
Both answers above are correct, but to fully understand how does it work I recommend you to learn how to use valgrind.
To check if program released memory correctly use
valgrind -v --leak-check=full --track-origins=yes ./your-program
This will execute your program on valgrind's virtual processor and give you full feedback about used resources.
Basically operator [] in C programming language in array definition context causes creation of (lets say to simplify) static array - this means that array is included in size of structure (if defined as part of structure) or is stored on the stack (if defined in function or globally).
The malloc function returns address of block of data you can use. Size of this block is at least as big as you requested. When you use free you release this block wich in this case means all data in block pointed by this address will be released.

C - Multiple malloc's for a struct-array inside a function

I've got a theoretical question on allocating memory for structs. Consider the following code IN THE MAIN FUNCTION:
I have the following struct:
typedef struct {
char *descr = NULL;
DWORD id = 0x00FFFF00;
int start_byte = 0;
int end_byte = 0;
double conversion_factor = 0.0;
} CAN_ID_ENTRY;
I want an array of this structs, so I'm allocating a pointer to the first struct:
can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY));
And then I'm allocating memory for the first struct can_id_list[0]:
can_id_list[0] = (CAN_ID_ENTRY *)malloc(sizeof(CAN_ID_ENTRY));
Now the problem is, that I don't know HOW MANY of these structs I need (because I'm reading a CSV-File and I don't know the amount of lines/entries). So I need to enlarge the struct-pointer can_id_list for a second one:
can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY));
And then I'm allocating the second struct can_id_list[1]:
can_id_list[1] = (CAN_ID_ENTRY *)malloc(sizeof(CAN_ID_ENTRY));
can_id_list[1]->id = 6;
Obviously, this works. But why? My point is the following: Normally, malloc allocates memory in one block in the memory (without gaps). But if another malloc is done BEFORE I'm allocating memory for the next struct, there is a gap between the first and the second struct. So, why can I access the second struct via can_id_list[1]? Does the index [1] store the actual address of the struct, or does it just calculate the size of the struct and jumps to this address beginning on the offset of the struct-pointer can_id_list (-> can_id_list+<2*sizeof(CAN_ID_ENTRY))?
Well, my real problem is, that I need to do this inside a function and therefore I need to pass the pointer of the struct to the function. But I don't know how to do this, because can_id_list is already a pointer ... and the changes must also be visible in the main method (that's the reason i need to use pointers).
The mentioned function is this one:
int load_can_id_list(char *filename, CAN_ID_ENTRY **can_id_list);
But is the parameter CAN_ID_ENTRY **can_id_list correct? And how do i pass the struct-array into this function? And how can i modify it inside??
Any help would be great!
EDIT: Casting malloc returns - Visual Studio forces me to do that! (Because it's a C++ project i think)
As the comments already said, the source of your confusion is can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY)); allocating the wrong amount of memory. It probably gave you space for a few pointers to be stored, not just one. Should be can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY*));.
To answer the question at the end,
But is the parameter CAN_ID_ENTRY **can_id_list correct? And how do i
pass the struct-array into this function? And how can i modify it
inside??
If you want to enlarge the size of the array within another function, you need to pass CAN_ID_ENTRY*** pr so you can set *ptr = realloc(...) inside as needed. Realloc may give you the new chunk of memory at a different address, so you can't simply pass in a CAN_ID_ENTRY** ptr then do realloc(ptr). See https://www.tutorialspoint.com/c_standard_library/c_function_realloc.htm

Struct pointer syntax confusion

Hi i'm relatively new to c and was wondering if anyone could explain what exactly i'm doing with the following code.
I have a struct:
typedef struct free_list_header {
u_int32_t magic; // ought to contain MAGIC_FREE
vsize_t size; // # bytes in this block (including header)
vlink_t next; // memory[] index of next free block
vlink_t prev; // memory[] index of previous free block
} free_header_t;
and I'm initialising it within a function using the following...
void vlad_init(u_int32_t size)
{
int sizePow2 = pow(2, ceil(log(size)/log(2)));
memory = malloc(sizePow2*sizeof(char));
memory_size = sizePow2;
strategy = BEST_FIT;
free_header_t *freeHeader = (free_header_t*)memory;
freeHeader->magic = MAGIC_FREE; // the unique value
freeHeader->size = memory_size; // amount we malloc'd
freeHeader->next = 0; // position of next free block
freeHeader->prev = 0; // position of prev free block
free_list_ptr = 0;
}
my question is what exactly am i doing here and why is it necessary?
free_header_t *freeHeader = (free_header_t*)memory;
So... i'm declaring a new struct by pointing to it named "freeHeader"? and that is a pointer to it in the memory i have allocated? So this is a way of putting the struct into the malloc'd area to access it out of the function in which im initializing it?
Malloc returns a void pointer (type void*). This means it returns a pointer to a memory address and that pointer is not pointing to any specific type. So after the line:
memory = malloc(sizePow2*sizeof(char)); //sizePow2 is n bytes to allocate
memory is a pointer of type (void *).
free_header_t *freeHeader = (free_header_t*)memory;
On the left hand side here you are creating a pointer named freeHeader that points to a memory address containing something of type free_header_t
Since you explicitly said this pointer is pointing to an address of type free_header_t to you are casting the other side (currently of type void *) to match it as free_header_t *.
NOTE in C, this works but is not necessary. The compiler will automatically cast a void * to whatever type you need. However writing code like this is good practice, in C++ you need to explicitly do this.
free_header_t * freeHeader = (free_header_t*)memory;
you declared a pointer (not an actual struct) to free_header_t struct named freeHeader and you assigned it the value of the pointer named memory. since memory is a pointer to char and yours is a pointer to something else, you used casting.
You currently have only a pointer to an allocated area (of size sizePow2*sizeof(char) - note that the size of the struct should be less or equal to the size of the allocated memory).
Your code is essentially equivalent to:
free_header_t *freeHeader = malloc(sizePow2 * sizeof(char));
It's allocating a block of memory that contains sizePow2 bytes, and then using that as the address of a free_list_header structure.
The reason it uses the memory variable is because some other code is going to use the next and prev members as indexes into that block of memory. As the name implies, this structure just contains the data at the beginning of the memory block, the rest of the memory is managed with other structures.
memory = malloc(sizePow2*sizeof(char));
You are allocating some memory here. It would be good to just use
memory = malloc(sizeof(struct free_list_header));
to store an object of the structure.
free_header_t *freeHeader = (free_header_t*)memory;
Here you are declaring a pointer which would point to memory allocated earlier. You did not technically declare an object of the structure. And you are not putting the structure in to malloc-ed area, you are instead treating the malloc-ed area as an object of the structure.
free_header_t freeHeader = {0}; would be declaring an object of the structure.
Every time you call malloc() function, the operating system returns you a single memory address. When you cast this pointer to a specific type you tell to compiler that every element stored in the memory allocated will consume the size of the specified type and this get the things easier.
Let suppose that you declare a uint64_t* and the size of allocation it's 100 times the size of uint64_t, so you're asking for 800 bytes for the operating system, once the uint64_t takes 8 bytes. If you do not cast this pointer, every time you increase the address with your_variable++ your program will skip only one byte and you will get in the "middle of the number and will get a weird value", but if you cast your pointer to a uint64_t and increase the address with your_variable++ your program will skip 8 bytes, going directly to the next number.
In your example, you're telling to the operating system that your pointer will store types of free_header_t. You're not obligated to do it, but it is a very good practice.
And yes, if you return this address to another function, the other function can change the value stored in this memory area easily.
Hope it helps!

free(struct variable) doesn't clear previous stored values associated with that variable when I malloc again?

I created a struct like the following:
typedef struct header{
int hc;
char src[18];
char dst=[18];
char reason[15];
char d[3];
char m[3];
char y[4];
struct measurements{
char h_ip[17];
int h_ttl;
int h_id;
float h_rtt;
}HOPS[100];
}HEADER;
INSIDE MAIN:
HEADER *head;
for(...){
head=(HEADER*) malloc(sizeof(HEADER));
.....
free(head);
}
Will the above malloc automatically allocate memory for the inner struct as well? Also, I'm facing a weird problem here. After I free the header, I'm still able to print the values of head->HOPS[i].h_ip. Should I explicitly free the inner struct as well so that even the values get cleared?
Yes, it allocates memory for the inner structure. And you need not free the inner structure separately.
If you have a pointer defined inside your structure, in that case you have to allocate separately for that pointer member of the structure and free that separately.
Consider freeing memory as a black box. All what you know is that after freeing you shouldn't refer to freed memory.
You may find that that memory block still exists and still contains some old values. That's ok: it just was marked as freed and probably it will be used again soon by allocator.
For example when you call malloc again and realized that just allocated block contains values from the old structure. It happens and that's alright. Just use this block as usually.
So, after the problem with the wrong declaration of head was resolved:
free returns a previously allocated memory block to the heap. It does not clear anything (for performance reasons). However, you are not supposed to access that block anymore afterwards. Doing so results in undefined behaviour and might let your computer fly out of the window.
Worst that can happen is ... nothing ... Yes, you might even not notice anything strang happens. However, that does not mean your program run correctly, it just does not show any symptoms.
To catch illegal accesses, you might set the pointer to NULL once you freed the object it points to. Some operating systems catch accesses to addresses near the null pointer address, but there is no guarantee. It is a good practice anyway and does no harm.
For your other question: malloc allocates a block of memory large enough to store that many bytes you passed as argument. If it cannot, it will return a null pointer. You should always check if malloc & friends returned a valid pointer (i.e. not a null pointer).
int *p = malloc(sizeof(int));
if ( p == NULL ) {
error: out of memory
}
...
Notice the omission of the cast of the result of malloc. In C you should not cast void * as returned by malloc & friends (but also elsewhere). As much as you did not for free(head). Both take the same type: void *, btw. (so why cast one and not the other?). Note that in C any object pointer can freely be assigned to/from void * without cast. Warning functions are no objects in the C standard!
Finally: sizeof(HEADER) returns the size of the struct. Of course that include all fields. A nested struct is a field. A pointer to another struct is a field. For the latter, however note: the pointer itself is a field, but not what it points to! If that was another struct, you have to malloc that seperately **and also free seperately (remember what I wrote above).
But as you do not have pointer inside your struct, that is not your problem here. (keep it in mind, if you continue programming, you will eventually need that!)

Freeing memory, all?

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);
}

Resources