I have a unsigned char* head that is pointing to a certain addess in memory and now I have to create a typedef struct that I've declared starting at the location of that pointer...I am confused on how to do that!
Here is the declaration of the typedef
typedef struct {
struct block *next;
struct block *prev;
int size;
unsigned char *buffer;
} block;
My assignment involves implementing malloc, so I can't use malloc. A block is part of a free_list which contains all chunks of free memory blocks that I have in my program heap. Hence, the previous and next pointers that point to the previous and next free blocks of memory.
Head points to the start of the free_list. When I have to split say the first block of free memory to satisfy a malloc() request that needs less space then that free block has I need to move my head and create a new block struct there.
Hope this makes sense. If not, the assignment looks something like this
Your struct has no tag, so you need to give it one in order for it to point to itself:
typedef struct block {
struct block *next;
struct block *prev;
int size;
unsigned char *buffer;
} block;
If you're using C99 you can initialise the memory at head directly, if necessary, without declaring a temporary struct block:
*(block *)head = (block){NULL, NULL, 0, NULL};
You now have a struct block at the address head, as long as you cast it properly.
e.g.
((block *)head)->size = 5;
Or you assign a cast pointer to it:
block *p = (block *)head;
p->size = 5;
unsigned char* head = /* whatever you have assuming that it has a sufficient size. */;
/* Create a block in memory */
block* b = (block*)malloc(sizeof(block));
/*
* modify data in b here as you wish.
*/
b->next = 0;
b->prev = 0;
/* etc... */
/* copy b to head */
memcpy(head, b, sizeof(block));
/* free block */
free(b);
The above assumes that head has enough space to store an instance of block.
What it does is create a block, and copy the memory to the position of head, then free the allocated block.
From comments:
head points to the start of a place in memory where I can overwrite data...You may assume that I have enough space!
Then to obtain a properly typed pointer:
struct block *p = (struct block *)head;
and to have a copy of the block:
struct block b = *(struct block *)head;
The operating system will provide an API call to allocate blocks of memory that your malloc can carve up and provide to callers. In Linux/unix look at sbrk. In Windows look at the Win32 heap API. Your records will point into this block. Making sure no two allocated sections of the block overlap is the job of your allocator code.
It looks like your records are implementing a free list. So how are you going to allocate list nodes when you don't have an allocator (yet)? The usual solution is to do it in the free blocks themselves. So a free block has the structure:
typedef struct free_block {
struct free_block *next, *prev;
size_t size;
unsigned char buffer[1];
} FREE_BLOCK;
Now this data structure actually lies at the start of a free block. Its buffer has only 1 byte in the declaration, but the actual buffer is size bytes. Initially you'd have something like:
static FREE_BLOCK *free_list = sbrk(ARENA_SIZE);
free_list->next = free_list->prev = free_list;
free_list->size = ARENA_SIZE - offsetof(FREEBLOCK, buffer);
This places the whole arena on the free list as a single block. Your allocator will search free_list to find a block that's big enough, carve out the piece it needs, put the remaining small block (if any) back on the free list. For freeing, it will add the freed block to the list and coalesce adjacent blocks.
Simple free list allocators differ in how they choose the free block to allocate from: first fit, rotating first fit, best fit, worst fit, etc. In practice rotating first fit seems to work as well as or better than any of the others.
Incidentally, all of the common algorithms implemented with free lists don't need double links. Single ones will do.
Since this is an academic assignment, it should be fine to just call malloc (instead of an operating system API) to establish the big block (often called the "arena") your allocator will manage. You could also declare a big array of bytes.
Related
I need some help with my assignment. My job is to create/implement malloc/free functions in C using “Explicit free list among only the free blocks” technique. I have already studied a lot of materials, but I am still stuck at some point and I do not understand some details. So my job is to create 4 functions – initialize(), allocate() ,free() and check(). I can use only one global variable void *memory – this is the block in which I can allocate my memory using alloc().
So I wanted to implement this using doubly linked-list and I created a structure:
typedef struct memoryBlock{
struct memoryBlock *prev,*next;
}memoryBlock;
And the structure for the header:
typedef struct header{
int size;
}header;
I was advised in my class to create a separate structure for a free memory block and another separate structure for an allocated block. My first idea was to distinguish the free/allocated blocks using one bit of the block size in header – set it to 1 if the block is allocated and 0 if it is free. ( I saw this technique used in implicit lists). So my question is: do I need to create a freeBlock and allocatedBlock structure for an explicit list or can I just use the one bit of the size?
The second question is: do I need a separate structure for the header/footer of the block? Or can I just write the size of the block in the header/footer as *(int *)ptr = size; ? I tried to use this in the initialize() function:
void initialize(void *ptr, int size){
memory = ptr;
*(int *)memory = size; //header
*((int *)memory + size) = size; //footer
}
Is this correct, please?
Many thanks for any help.
do I need to create a freeBlock and allocatedBlock structure for an explicit list[…]?
This sound to me like a very good idea. Just don't misunderstand the advice: You don't need two different structure definitions but two different lists. You can realize this with two pointers, one for free blocks and one for allocated blocks.
[…] can I just use the one bit of the size?
You can only use one bit of size if it is unused otherwise. If you choose bit 0 it will only work when only even numbers of memory words are allocated.
do I need a separate structure for the header/footer of the block?
That depends on your design and algorithm. Are you bound to create a header and a footer?
Or can I just write the size of the block in the header/footer as *(int *)ptr = size;?
You can do this. But I would assign the given pointer to a (temporary) pointer to the right struct and then assign values right in their places.
void initialize(void *ptr, int size) {
memory = ptr;
header* h = memory;
h->size = size;
}
Additional observation: Instead of
typedef struct memoryBlock{
struct memoryBlock *prev,*next;
}memoryBlock;
better get used to this, it will save you a lot of pulled-out hair:
typedef struct memoryBlock {
struct memoryBlock *prev;
struct memoryBlock *next;
} memoryBlock;
Note: Due to the (seemingly) complexity of pointer, please raise the warning level of you compiler to the maximum. Read all warnings and eliminate their reasons.
I have the following struct which I use to implement a priority queue
struct q_element
{
//Declaration of struct members
int element;
int priority;
struct q_element *next_element;
};
and I use a pointer to a struct 'cur' to start from the first item in the queue
struct q_element* cur = start_element;
and keep moving until I find the one I want to delete from list.
while (cur->priority!=max_priority)
cur = cur->next_element;
Does the following line of code actually free the struct? Because 'cur' is a pointer to the struct I wasn't completely sure.
free(cur);
You need to pass a pointer to free, so free(cur) is the way to go, assuming that the struct itself has been allocated using malloc/calloc/realloc. Specifically, if you allocated your curr in the automatic memory (i.e. on the stack) you are not supposed to call free on it.
It looks like q_element is part of a linked list. Freeing the struct itself will not free other structs pointed to by it, so if you'd like to free the struct along with its tail, you need to write a loop.
Finally, when you free memory pointed to by some pointer in your program, it is a very good idea to assign NULL to the pointer that you freed to avoid accidental double-freeing and undefined behavior on accessing freed memory.
I wanted to create a generic Linked List in C. Following is the structure of the node:
typedef struct node {
void *value;
int size; // n bytes
ind index; // index of the node
struct node *next;
} Node;
And my delete_node function is as following. The search function sends a pointer to the Node I want to delete.
Node *search_list(Node *list, void *data, int n_bytes);
int delete_node(Node *list, Node *to_be_deleted); // returns 1 on success
Inside the delete_node function I want to free up the memory pointed by void *value and then free up the memory allocated for the Node itself.
free(to_be_deleted->value); // Would this work??
free(to_be_deleted);
Since it is void pointer we don't know that how many bytes the object it is pointing to has occupied. How can we free up the memory for that?
Sorry if it is a stupid questions?
The memory allocator keeps track of how large memory allocations are on its own -- there's no need to tell free() how much memory to free.
As such, you should be able to just get rid of size and n_bits.
free(to_be_deleted->value); // Would this work??
Straight forward answer , Yes this will work.
simple thing :
see the definitions of free() and malloc()
void free(void *) // free takes void* as argument so it will work
void* malloc(sizeof(type))
In mallocwe have to pass thesize that how many bytes we want to allocate.
but in free just pass the pointer and whatever bytes allocated to that pointer on heap storage it will be freed
Yes, what you wrote should work. The reason is that malloc (which is a library call) creates metadata that is used to determine which parts of memory are free and which ones are taken. When you call free(), you are actually only modifying this metadata such that subsequent calls to malloc know that this memory can be re-used (note that most implementations will not zero the existing data).
If I have a snippit of my program like this:
struct Node *node;
while(...){
node = malloc(100);
//do stuff with node
}
This means that every time I loop through the while loop I newly allocate 100 bytes that is pointed to by the node pointer right?
If this is true, then how do I free up all the memory that I have made with all the loops if I only have a pointer left pointing to the last malloc that happened?
Thanks!
Please allocate exactly the size you need: malloc(sizeof *node); -- if you move to a 64-bit platform that doubles the size of all your members, your old 96-byte structure might take 192 bytes in the new environment.
If you don't have any pointers to any of the struct Nodes you have created, then I don't think you should be allocating them with malloc(3) in the first place. malloc(3) is best if your application requires the data to persist outside the calling scope of the current function. I expect that you could re-write your function like this:
struct Node node;
while(...){
//do stuff with node
}
or
while(...){
struct Node node;
//do stuff with node
}
depending if you want access to the last node (the first version) or not (the second version).
Of course, if you actually need those structures outside this piece of code, then you need to store references to them somewhere. Add them to a global list keeping track of struct Node objects, or add each one to the next pointer of the previous struct Node, or add each one to a corresponding struct User that refers to them, whatever is best for your application.
If you set node = NULL before the loop and then use free(node) before node = malloc(100) you should be OK. You will also need to do a free(node) after the loop exits. But then again, it all depends on what "//do stuff with node" actually does. As others have pointed out, malloc(100) is not a good idea. What I would use is malloc(sizeof(*node)). That way, if the type of node changes, you don't have to change the malloc line.
If you don't need the malloc'ed space at the end of one iteration anymore, you should free it right away.
To keep track of the allocated nodes you could save them in a dynamically growing list:
#include <stdlib.h>
int main() {
int i;
void *node;
int prt_len = 0;
void **ptrs = NULL;
for (i = 0; i < 10; i++) {
node = malloc(100);
ptrs = realloc(ptrs, sizeof(void*) * ++prt_len);
ptrs[prt_len-1] = node;
/* code */
}
for (i = 0; i < prt_len; i++) {
free(ptrs[i]);
}
free(ptrs);
return 0;
}
Note: You should probably re-think your algorithm if you need to employ such methods!
Otherwise see sarnold's answer.
then how do I free up all the memory that I have made with all the loops if I only have a pointer left pointing to the last malloc that happened?
You can't. You just created a giant memory leak.
You have to keep track of every chunk of memory you malloc() and free() it when you're done using it.
You can not. You need to store all the pointer to free the memory. if you are saving those pointer somewhere then only you can free the memory.
I'm just reading about malloc() in C.
The Wikipedia article provides an example, however it justs allocate enough memory for an array of 10 ints in comparison with int array[10]. Not very useful.
When would you decided to use malloc() over C handling the memory for you?
Dynamic data structures (lists, trees, etc.) use malloc to allocate their nodes on the heap. For example:
/* A singly-linked list node, holding data and pointer to next node */
struct slnode_t
{
struct slnode_t* next;
int data;
};
typedef struct slnode_t slnode;
/* Allocate a new node with the given data and next pointer */
slnode* sl_new_node(int data, slnode* next)
{
slnode* node = malloc(sizeof *node);
node->data = data;
node->next = next;
return node;
}
/* Insert the given data at the front of the list specified by a
** pointer to the head node
*/
void sl_insert_front(slnode** head, int data)
{
slnode* node = sl_new_node(data, *head);
*head = node;
}
Consider how new data is added to the list with sl_insert_front. You need to create a node that will hold the data and the pointer to the next node in the list. Where are you going to create it?
Maybe on the stack! - NO - where will that stack space be allocated? In which function? What happens to it when the function exits?
Maybe in static memory! - NO - you'll then have to know in advance how many list nodes you have because static memory is pre-allocated when the program loads.
On the heap? YES - because there you have all the required flexibility.
malloc is used in C to allocate stuff on the heap - memory space that can grow and shrink dynamically at runtime, and the ownership of which is completely under the programmer's control. There are many more examples where this is useful, but the one I'm showing here is a representative one. Eventually, in complex C programs you'll find that most of the program's data is on the heap, accessible through pointers. A correct program always knows which pointer "owns" the data and will carefully clean-up the allocated memory when it's no longer needed.
What if you don't know the size of the array when you write your program ?
As an example, we could imagine you want to load an image. At first you don't know its size, so you will have to read the size from the file, allocate a buffer with this size and then read the file in that buffer. Obviously you could not have use a static size array.
EDIT:
Another point is: When you use dynamic allocation, memory is allocated on the heap while arrays are allocated on the stack. This is quite important when you are programming on embedded device as stack can have a limited size compared to heap.
I recommend that you google Stack and Heap.
int* heapArray = (int*)malloc(10 * sizeof(int));
int stackArray[10];
Both are very similar in the way you access the data. They are very different in the way that the data is stored behind the scenes. The heapArray is allocated on the heap and is only deallocted when the application dies, or when free(heapArray) is called. The stackArray is allocated on the stack and is deallocated when the stack unwinds.
In the example you described int array[10] goes away when you leave your stack frame. If you would like the used memory to persist beyond local scope you have to use malloc();
Although you can do variable length arrays as of C99, there's still no decent substitute for the more dynamic data structures. A classic example is the linked list. To get an arbitrary size, you use malloc to allocate each node so that you can insert and delete without massive memory copying, as would be the case with a variable length array.
For example, an arbitrarily sized stack using a simple linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct sNode {
int payLoad;
struct sNode *next;
} tNode;
void stkPush (tNode **stk, int val) {
tNode *newNode = malloc (sizeof (tNode));
if (newNode == NULL) return;
newNode->payLoad = val;
newNode->next = *stk;
*stk = newNode;
}
int stkPop (tNode **stk) {
tNode *oldNode;
int val;
if (*stk == NULL) return 0;
oldNode = *stk;
*stk = oldNode->next;
val = oldNode->payLoad;
free (oldNode);
return val;
}
int main (void) {
tNode *top = NULL;
stkPush (&top, 42);
printf ("%d\n", stkPop (&top));
return 0;
}
Now, it's possible to do this with variable length arrays but, like writing an operating system in COBOL, there are better ways to do it.
malloc() is used whenever:
You need dynamic memory allocation
If you need to create array of size n, where n is calculated during your program execution, the only way you can do it is using malloc().
You need to allocate memory in heap
Variables defined in some functions live only till the end of this function. So, if some "callstack-independent" data is needed, it must be either passed/returned as function parameter (which is not always suitable), or stored in heap. The only way to store data in heap is to use malloc(). There are variable-size arrays, but they are allocated on stack.