I was looking into some memory management (pool + malloc + free) implementations using linked list, and I found that in most of them each node is something like this:
typedef struct node{
int usedSize;
node* next;
char mem[100];
}
and then the free(ptr) must be:
free(void* ptr){
node* item = (node*)((char*)ptr - sizeof(node*) - sizeof(int));
\\some code to put the "item" back to the pool
}
My question is this:
why shouldn't we put the char mem[100]; in the beginning of the structure to avoid the "pointer manipulation"?
the result is:
typedef struct node{
char mem[100]; // moved to the beginning
int usedSize;
node* next;
}
and then the free(ptr) is simpler:
free(void* ptr){
node* item = (node*)((char*)ptr);
\\some code to put "item" back to the pool
}
Thanks.
That pointer manipulation is not particularly complicated. It amounts to a decrement by a compile time constant. As noted in comments, it should actually be:
node* item = (node*)((char*)ptr - offsetof(struct node, mem));
Placing that header above the memory allows the memory to be represented by a flexible array member. A flexible array member can only occupy the last position of a structure. This was also noted in comments.
typedef struct node {
int usedSize;
node* next;
char mem[];
} node;
If the size of the memory is large, jumping over the array to reach the next pointer will likely flush data cache lines to load the bookkeeping data. However, a short jump backward from the array will likely access the data already loaded into the cache.
Related
as for a little project, my aim is to add a node at the head of a linked-list and allocate "width" bytes of data for the struct Node structure. Normally, this would be simple as malloc accomplishes this task; however, I've been instructed to use a function called newmalloc, which essentially does the same thing. The newmalloc function returns an integer which is what will be used as the number of bytes to allocate the structure. I have provided my header file which contains the struct, as well as the function in which I am working.
Header.h:
#include <stdio.h>
struct Node {
int data;
int next;
};
void push(int*node_ptr, void*pie, size_t width );
Function.c:
void push(int *node_ptr, void *pie, size_t width) {
struct Node *next, *prev, *head, *p;
newmalloc(width); //Returns number of bytes
}
How do I actually go about allocating memory for the struct Node structure using the returned integer from newmalloc, without using malloc? Thanks for the help!
If I have a long char array[100], which store a list of structs in it, and if I want to add one one struct in the end, how do I check if it exceeds the boundary or not?
For example,
static char arr[100];
typedef NODE* node_ptr;
typedef struct node
{
char a;
char b;
int size;
node_ptr next;
}NODE;
//arr already contains few node in it.
//size: the new node size, I want to add in the end
node_ptr add_node(node_ptr last, size_t size)
{
node_ptr new;
if(last+2*sizeof(NODE)+size<arr+100)
//add new node
return new;
}
How can I check if new node exceed the array boundary?
this is COMMENT
do not upvote - but feel free to DV.
You ask difficult question and it is not easy to answer. You need also to consider some more complex cases like
or
or
Small array will become fragmented in a very short time. This is one of the reasons why uC developers try to avoid this kind of memory allocation. There are other techniques like pools used in the embeedded programming.
First time asking a question but I did look around Google and stackoverflow to see if someone has asked something similar before. In malloc, recasting and free, it looked like the OP asked something similar for example. But it was more complicated.
I was wondering whether it's possible to create a generic function for a list structure in C that traverses the list given that you know that the different types of structures will always have a "next" field.
For example, given these two list-type structures:
typedef struct _list1 {
int value;
list1 *next;
} list1;
typedef struct _list2 {
int value;
char *string;
list2 *next;
} list2;
Is it possible to create a generic void freeList((void *) list) function or something which looks something like the below? I am aware it's a simple thing to write both free functions for each individual list separately.
void freeList((void *) list) {
// Included this because the structs would have different sizes
// so I thought it would be possible to cast it in order to properly dereference the field.
if (sizeof *list == sizeof list1)
*list = (list1) list;
else if (sizeof *list == sizeof list2)
*list = (list2) list;
if (!list) return;
else {
free(list->next);
free(list);
}
}
So far, my experiments with the code shown above didn't fare well given that gcc would complain about dereferencing a void * pointer.
Making a heterogeneous list can be achieved by the use of a tagged union, or just a tag and casting:
struct list_item {
struct list_item *next;
enum datatype type;
void *contents;
};
or
struct list_item {
struct list_item *next;
enum datatype type;
union {
int some_int;
char some_char;
} contents;
};
Then while traversing the list you just have to verify the type stored in type before using the contents of the element.
This check:
if (sizeof *list == sizeof list1)
*list = (list1) list;
else if (sizeof *list == sizeof list2)
*list = (list2) list;
doesn't work because sizeof is a static construct: its value is defined at compilation time. You're just asking for the sizeof void.
is it possible to create a generic function for a list structure in C that traverses the list given that you know that the different types of structures will always have a "next" field.
Yes, as mentioned before; you must be careful that every structure starts with the "next" field; the two structures in your post should therefore be reordered like this:
typedef struct _list1 {
list1 *next;
int value;
} list1;
typedef struct _list2 {
list2 *next;
int value;
char *string;
} list2;
It is not clean code, because the compiler could reorder (and pad) the fields of the structure, but in general it should work.
Is it possible to create a generic void freeList((void) *list) function or something which looks something like...
This is possible if your structs do not refer malloced memory; or they do, but in a uniform (and known) way (note the first case is a sub-case of this last).
If the structs contain pointers pointing to memory that has to be freed, in fact, while freeing the struct the freeList() function should also free the referenced memory. A few solutions come to my mind:
1 - If all the different structs contain the same "pointers" layout, the routine can free those pointers in a uniform manner, knowing in advance what to do. In such scenario, one can also use pointer fields that are not used by all the structs, but only some.
2 - Every single instance of a struct could contain some helper field describing the pointer's layout. For example, just after the "next" field, another "mempntcnt" field could tell how many pointers (to be freed) follow the "next" field. Or, this "mempntcnt" could be passed as a parameter to freeList().
3 - This problem could be managed by a totally separated mechanism, outside the scope of freeList(). Much depends on the final usage: I mean, for a given (kind of) linked list, first call a routine that frees all the memory referenced by the list itself, then free the list by calling the common freeList(). After all, if different structs are needed, then different routines are used on them...
I hope I've been clear enough...
If you ensure that the next pointer is the first member of the struct then this is possible.
typedef struct list1 {
// next pointer must be first
struct list1 *next;
int value;
} list1;
typedef struct list2 {
// next pointer must be first
struct list2 *next;
int value;
char *string;
} list2;
void freeList(void *list) {
if (list) {
freeList(*(void**)list);
free(list);
}
}
Im trying to create a linked list in C, where each node has a specific size entered by the user when the program launches. I already thought of a struct:
struct ListNode{
char * str;
struct ListNode * next_node;
};
but here the size of each node is fixed. Any ideas?
Thanks a lot in advance.
It seems you need your data size that the node holds to change each time. You can achieve this by using a constant size node that holds a pointer to dynamically allocated data.
Note that in the example below the struct size stays sizeof(void*)+ sizeof(node*)
but the size of data allocated for each node changes using the user input.
typedef struct Dnode
{
void* data;
struct Dnode* next;
}Dnode;
Dnode* CreateDnode(size_t data_size_bytes)
{
Dnode* newNode = NULL;
newNode = malloc(sizeof(Dnode));/*always the same*/
if(NULL == newNode)
{
return NULL;
}
newNode->data = malloc(data_size_bytes);/*changes by input*/
if(NULL == newNode->data)
{
return NULL;
}
newNode->next = NULL;
return newNode;
}
Sounds like you may be looking for the "flexible array member" feature whereby an incomplete array is placed at the end of a structure:
struct ListNode {
struct ListNode *next;
char data[];
};
This is allocated like:
struct ListNode *node = malloc(sizeof *node + data_size_bytes);
Then we can store values in node->data[i] for i from 0 to data_size_bytes - 1. The whole structure and data are in one linear block.
Note that a structure with a flexible member can't be used as an array element type.
Before the ISO C standard added the flexible array member in 1999, this was done as a popular "struct hack" using an array of size 1. If you're constrained to working in C90 it goes like this:
struct ListNode {
struct ListNode *next;
char data[1];
};
Now sizeof ListNode includes the one element array, and quite likely padding for alignment. For instance on a system with four byte pointers, the size is quite likely eight. If we use the same malloc line, we will allocate excess memory. The right malloc expression to use for the C90 struct hack:
#include <stddef.h>
struct ListNode *node = malloc(offsetof(struct ListNode, data) + data_size_bytes);
Unlike the flexible array member feature, the struct hack doesn't have formally well-defined behavior; it's just something that "works if it works".
This is code for a linked list in the C programming language.
#include <stdio.h> /* For printf */
#include <stdlib.h> /* For malloc */
typedef struct node {
int data;
struct node *next; /* Pointer to next element in list */
} LLIST;
LLIST *list_add(LLIST **p, int i);
void list_remove(LLIST **p);
LLIST **list_search(LLIST **n, int i);
void list_print(LLIST *n);
The code is not completed, but I think it's enough for my question. Here at the end of struct node "LLIST" is used, and it's also used as a return type in the prototyping of the function list_add. What is going on?
That's a typedef. It's actually doing two things at once. First, it defines a structure:
struct node {
int data;
struct node *next;
}
And then does a typedef:
typedef struct node LLIST;
That means LLIST is a type, just like int or FILE or char, that is a shorthand for struct node, your linked-list node structure. It's not necessary - you could replace LLIST with struct node in all of those spots - but it makes it a bit easier to read, and helps hide the implementation from pesky end-users.
LLIST is just another type name for the struct that has been created. In general, the following format will create a type "NAME" that is a "struct x":
typedef struct x { ... } NAME;
C requires that you reference structs with a "struct" prefix, so it's common to introduce a typedef for less verbose mention.
That is, the declaration of your struct has two parts, and can be rewritten as such:
struct node {
int data;
struct node *next; /* pointer to next element in list */
};
typedef struct node LLIST;
So, LLIST is just another name for struct node (thanks Chris Lutz).
typedef creates a new "type" in your program, so the return value and types of parameters of those functions are just your struct. It is just shorthand for using struct node for the type.
If you were to create a new node, you could do it like this (using the type):
LLIST *node = malloc(sizeof(LLIST));
node->data = 4;
node->next = someOtherItem;
list_add(node, 1)
Also, with the function prototypes in your question, you don't really need the double pointers; since the data in your struct is just an int, you could do something like
LLIST *list_add(int data, int position);
then the list_add function would handle the allocation, copy the int into the struct and add it to the linked list.
Putting it in at a certain position is as simple as changing the next pointer in the node before it to the address of the newly allocated node, and the next pointer in the new node to point at the next one (the one the node before that one was originally pointing at).
Keep in mind that (given the rest of your function prototypes) you will have to keep track of pointers to every node you create in order to delete them all.
I'm not sure I understand how the search function will work. This whole thing could be implemented a lot better. You shouldn't have to provide the location of a node when you create it (what if you specify a higher number than there are nodes?), etc.
LLIST* is a pointer to a structure defined by the LLIST struct.
You should do
LLIST* myList = malloc(sizeof(LLIST)*number_of_elements);
to have some memory allocated for this list. Adding and removing items requires you to reallocate the memory using realloc. I've already written some piece of code for lists (made with arrays).
I might post the code as soon as I'm home, which is currently not the case.