I am building a custom allocator. I am calling mmap() the first time and then I am constructing an explicit freelist. Everything works fine, but when I need to split an existing block I do not seem to be able to initialize an object from a void* (my C fundamentals are quite rusty). I know it sounds confusing so here is the code that I have.
// this is the struct I am using to keep track of the free nodes
struct Node {
size_t header;
void* payload;
}
when I split, I decrease the size of the big node
void* split_block(Node* good_node, size_t reqsize) {
DECREASE_SIZE(good_node)
Node* prev_node = (Node*)(good_node -> payload);
Node* next_node = (Node*)((good_node -> payload) + 8);
}
I store the pointers to next and previous node. IMPORTANT, the pointer are inside the payload, specifically prev = payload, next=payload+8.
Now the problem. How do I construct a node from the raw memory (payload).
The code that does not work is this
// I omit the calculation of the address at which
// the split_part is going to end up
Node* split_part = GET_HEADER_POSITION(good_node, reqsize);
split_part->header = some_value;
split_part->payload = prev_node;
split_part->payload[1] = next_node;
I did not construct the object. But how can I do so, should not this work just like when I malloc memory?
Node* node = malloc(sizeof(Node));
Thank you for the attention.
Related
I have this function which should copy a node in a linked list(not first of it)
struct Node {
char* data;
Node* next;
};
void Insert(Node*head, int index, char* data) {//find a is function to find needed position
Node* temp = find(head, index);
Node* t = (Node*)malloc(sizeof(Node));
t->data = (char*)malloc(100);//where the problem is //line 4
strcpy(t->data, data);
t->next = temp->next;
temp->next = t;
}
it will work well if line 4 is in my code. I have read this question:
crash-or-segmentation-fault-when-data-is-copied-scanned-read-to-an-uninitializ
so I know pointer cannot contain any data and I cannot copy/store data into a pointer. So, as you see I allocated memory for it first and then placed data in it, otherwise my program will crash.
But then I used this: t->data = data; and it worked, so I want to know: why when I use strcpy like this strcpy(t->data, data);, I need to allocate memory for t->data first, otherwise my program will crash; but this t->data = data; will work well, without the requirement to allocate memory?
Can you explain this to me?
PS:casting malloc is because of using c++ compiler.
When you use the code t->data = data you are not copying any data to your node! All you are doing is make the node's data member point to the data that the function's argument also points to - so, if you later change that data, then you will also change the node's data. This is probably not what you intend! For example, if you call the function several times from 'the outside' and use the same variable to pass the data in, then each of your added nodes will have a data member pointing to the same piece of data.
If you actually want to copy the data from the argument to your new node (as your call to strcpy does), then you must first allocate storage space for it, using (in your code) the malloc function.
But, as mentioned in the comments, the strdup function is much more convenient here: this both allocates the (exact required amount of) memory and copies the data in one fell swoop:
t->data = strdup(data);
Note: The memory allocated by strdup needs to be released (with a call to free) when you're done with it, in just the same way as memory allocated by malloc.
Code only allocated for a size of a pointer when the size of the referenced object is needed.
// Node* t = (Node*)malloc(sizeof(Node*));
Node* t = (Node*)malloc(sizeof(Node));
Even better is to size to referenced object rather than the type. Cast not needed either.
Node* t = malloc(sizeof *t);
String allocation is suspicious too. Rather than a fixed 100, I'd expect an allocation to the size of the string.
//t->data = (char*)malloc(100);
//strcpy(t->data, data);
size_t len = string(data);
t->data = malloc(len + 1);
strcpy(t->data, data);
Robust code would check for allocation errors.
Node* t = malloc(sizeof *t);
if (t == NULL) Handle_OutOfMemory();
Okay this question may sound stupid to the amateur programmers . But seriously this is bothering me and a solemn answer to this doubt of mine is welcomed. I have just started to take my first ever course in data structures. And what is bothering me is this:
Assuming C is used,
//Implementing a node
struct Node
{
int data;
struct *Node;
};
Now while creating a node why do we use the dynamic memory allocation technique where we use malloc(). Can't we just create a variable of type ' Struct Node '.
i.e. something like:
struct Node N1;
//First node - actually second where !st Node is assumed to be Head.
struct Node *Head = &N1;
struct Node N2;
N2.(*Node) = &N1;
Well some parts of my code may be incorrect because I am only a beginner and not well versed with C. But by know you may have understood what I basically mean. Why don't we create variables of type Node of an Array of type Node to allocate memory t new nodes why get into the complexity of dynamic memory allocation?
First off, you have an error in how you declare your struct. struct * by itself does not denote a type. You have to give the full type name:
struct Node
{
int data;
struct Node *Node;
};
You can certainly use local variables as above to make a linked list, however that limits you to a fixed number of list elements, i.e. the ones you explicitly declare. That would also mean you can't create a list in a function because those variables would go out of scope.
For example, if you did this:
struct Node *getList()
{
struct Node head, node1, node2, node3;
head.Node = &node1;
node1.Node = &node2;
node2.Node = &node3;
node3.Node = NULL;
return &head;
}
Your list would be restricted to 4 elements. What of you needed thousands of them? Also, by returning the address of local variables, they go out of scope when the function returns and thus accessing them results in undefined behavior.
By dynamically allocating each node, you're only limited by your available memory.
Here's an example using dynamic memory allocation:
struct Node *getList()
{
struct Node *head, *current;
head = NULL;
current = NULL;
// open file
while (/* file has data */) {
int data = /* read data from file */
if (head == NULL) { // list is empty, so create head node
head = malloc(sizeof(struct Node *));
current = head;
} else { // create new element at end of list
current->next = malloc(sizeof(struct Node *));
current = current->next;
}
current->data = data;
current->Node = NULL;
}
// close file
return head;
}
This is psedo-code that doesn't go into the details of reading the relevant data, but you can see how you can create a list of arbitrary size that exists for the lifetime of the program.
If these variables are local, defined inside a function's scope (i.e. stored on the stack), you shouldn't do this, because accessing them after leaving their scope will result in undefined behavior (their contents will likely be overwritten as you call other functions). In fact, any time you return a pointer to a local, stack based variable from your function, you are doing the wrong thing. Given the nature of C, this is problematic since nothing will warn you you are doing something wrong, and it will only fail later when you try to access this area again.
On the other hand, if they are declared as global variables (outside any other function), then you are simply limited by the number of variables declared that way.
You can potentially declare many variables, but keeping track of which one is "free" for use will be painful. Sure, you can even go a step further and say you will have a global preallocated array of nodes to prevent using malloc, but as you are doing all this you are only getting closer to writing your own version of malloc, instead of sticking to the existing, dynamic one.
Additionally, all preallocated space is wasted if you don't use it, and you have no way of dynamically growing your list in runtime (hence the name dynamic allocation).
Here is some good reasons to use dynamic memory
When you declare node struct Node N1;this node will store on stack memory. After scope of the node that will get destroy auto.But in case of dynamic you have handle to free the memory when you done.
When you have some memory limitation.
When you don't know the size of array then dynamic memory allocation will help you.
One issue could be that you cannot use another function to add a new node to your list.
Remember that automatic variables - like the ones created by struct Node node100; - have scope only inside the function in which they are defined. So when you do something like this:
int main()
{
struct Node *head;
/* Some code there you build list as:
head ---> node1 ---> node2 --> .. ---> node99
*/
/* Add a new node using add_node function */
add_node(head, 555);
/* Access the last node*/
}
void add_node(struct Node *head, int val)
{
/* Create new node WITHOUT using malloc */
struct Node new_node;
new_node.data = val;
/* add this node to end of the list */
/* code to add this node to the end of list */
/* last_element_of_list.next = &new_node*/
return;
}
Now you think that you have added a new node to the end of the list. But, unfortunately, its lifetime ends as soon as the add_node function returns. And when you try to access that last node in your main function your program crashes.
So, to avoid this situation you will have put all your code in one single function - so that the lifetime of those nodes do not end.
Having all your code in ONE function is bad practice and will lead to many difficulties.
This was one situation that asks for a dynamic memory allocation, because, a node allocated with malloc will be in scope untill it is freed using free, and you can put code that do different things in different functions, which is a good practice.
You don't have to use dynamic memory to create a linked list, although you definitely don't want to create separate variables for each node. If you want to store up to N items, then you'd need to declare N distinct variables, which becomes a real pain as N gets large. The whole idea behind using a linked list is that it can grow or shrink as necessary; it's a dynamic data structure, so even if you don't use malloc and free, you're going to wind up doing something very similar.
For example, you can create an array of nodes at file scope like so:
struct node {
int data;
struct node *next;
};
/**
* use the static keyword to keep the names from being visible
* to other translation units
*/
static struct node store[N]; /* our "heap" */
static struct node *avail; /* will point to first available node in store */
You the initialize the array so each element points to the next, with the last element pointing to NULL:
void initAvail( void )
{
for ( size_t i = 0; i < N - 1; i++ )
store[i].next = &store[i + 1];
store[N - 1].next = NULL;
avail = store;
}
To allocate a node for your list, we grab the node avail points to and update avail to point to the next available node (if avail is NULL, then there are no more available nodes).
struct node *getNewNode( void )
{
struct node *newNode = NULL;
if ( avail ) /* if the available list isn't empty */
{
newNode = avail; /* grab first available node */
avail = avail->next; /* set avail to point to next available node */
newNode->next = NULL; /* sever newNode from available list, */
} /* which we do *after* we update avail */
/* work it out on paper to understand why */
return newNode;
}
When you're done with a node, add it back to the head of the available list:
void freeNode( struct node *n )
{
n->next = avail;
avail = n;
}
We're not using dynamic memory in the sense that we aren't calling mallic or free; however, we've pretty much recapitulated dynamic memory functionality, with the additional limitation that our "heap" has a fixed upper size.
Note that some embedded systems don't have a heap as such, so you'd have to do something like this to implement a list on such systems.
You can write a singly linked list with out malloc , but make sure the implementation is done in main. but what about writing program for traversing , finding least number ,etc . these struct node variables will go out of scope .
struct node{
int a;
struct node* nextNode;
};
int main()
{
struct node head,node1,node2;
head.a=45;
node1.a=98;
node2.a=3;
head.nextNode=&node1;
node1.nextNode=&node2;
node2.nextNode=NULL;
if(head.nextNode== NULL)
{
printf("List is empty");
}
struct node* ptr=&head;
while(ptr!=NULL)
{
printf("%d ",ptr->a);
ptr=ptr->nextNode;
}
}
I have a working implementation of my code with a ton of mallocs. It has
struct* node myList;
struct node { ... } // contains stuff
struct* node_constructor(...) {
node* tempnode = (node*) malloc(sizeof(node));
node* next = ...;
... // some other info
}
and then in my main function I call
myList = node_constructor(myList,otherarguments...);
I'm thinking there's probably a way to do something like
temp = (node*) malloc(sizeof(node)*numberOfNodes);
for(i=0; i<numberOfNodes;i++) { temp[i].next = temp[i-1]; ... } // wrong?
temp[numberOfNodes-1]; // set myList equal to the last one
and get rid constructor function and all those individual mallocs, I just seem to be getting confused with what to do with my malloced space. So temp is a (node*), so I'm pretty sure my temp[i].next = temp[i-1] thing is wrong...and maybe some of the other ideas are too. If anyone has any advice/input, I'd appreciate it.
Ok, Sure, you could do that, kinda. As long as temp is big enough and you know that size beforehand. And temp would more likely be a void* or some generic container just to hang onto unspecified memory rather than node. (Because it's not a node, it's where all your nodes go. temp[x] when temp is malloced is kind of a hack).
But now you want to add another node to your list. How do you do that?
The individual mallocs let you add a single item to the list. And if you are in a situation where you want to add a number of items to your list, then you can just call the individual functions multiple times.
The idea of allocating a large pool of memory, and divvying it up into the piecemeal sections later is a valid idea and it has some performance benefits, but it's of limited niche use.
Allocating just enough memory for one more item is a lot more handy and common. You're not wrong, but trust me, learn how to do it the normal way first.
If you are going to back your list with an array there is no need to have next pointers - the next object is the next index in the array.
There are both advantages and disadvantages with an array list implementation compared to a linked list implementation.
Ideally, you would have a node like this:
typedef struct node
{
struct node* next;
struct node* prev; // optional for double-linked list
uint8_t* data;
size_t data_size;
} node_t;
and then create it as
result_t list_add (const void* data, size_t size)
{
if(list_is_full()) // if applicable
{
return list_is_full_error;
}
node_t* new_node = node_constructor(data, size);
if(new_node == NULL)
{
return memory_error;
}
list_add(new_node);
return ok;
}
static node_t* node_constructor (const void* data, size_t size)
{
node_t* new_node = malloc(*new_node);
if(new_node == NULL)
{
return NULL;
}
new_node->data = malloc(size);
if(new_node->data == NULL)
{
return NULL;
}
new_node->size = size;
memcpy(new_node->data, data, size);
return new_node;
}
static void list_insert (node_t* new_node)
{
// add the node to the linked list here
// set next/prev pointers of the new node and of adjacent nodes
// increase node counter (linked list size) if applicable
}
I was trying to make a linked list working for my module, I am not using the build-in kernel linked list( I don't know that thing exist at the moment when I started making my module).
here is my struct
struct data{
struct data *next;
struct msghdr *msg;
size_t len;
}
I make a head as global variable.
struct data *head = NULL;
I have a add_to_end function
void add_to_end(struct data *newData){
struct data *temp1;
if (head == NULL){
head = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
head = newData;
} else {
temp1 = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
temp1 = head;
while(temp1->next!=NULL) {
temp1 = temp->next;
}
temp1->next = newData;
}
}
in one of my functions, I use add_to_end like this
struct data *temp;
temp = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
temp->next = NULL;
temp->msg = (struct msghdr *)kmalloc(sizeof(struct msghdr),GFP_KERNEL);
temp->msg = message;
temp->len = length;
add_to_end(temp);
but when I am trying to use the msg in this linked list, error happens. The kernel print some trace thing to the terminal.
What I want to do is copy the message into my linked list, but as a separate copy, not just copying the pointer that point to the address. I have read some examples that when copying two struct, they actually using the same address, when changing one of them, both of them got changed. I don't want that kind of copy, I want a separate copy with its own address.
I am guessing that the way that I copy the two struct is not right and maybe my linked list is not right too, can someone help me please?
1) You have to use memecpy function to copy content from message to your data structure.
temp->msg = (struct msghdr *)kmalloc(sizeof(struct msghdr),GFP_KERNEL);
// temp->msg = message;
memcpy(temp->msg, message, sizeof(struct msghdr));
2) If the message is pointer point to a memory buffer in user space, you have to use the copy_from_user() function instead of memcpy. This function will handle the user space to kernel space memory copy.
3) Please do not reinvent the wheel. The kernel already has link list structure herel and your can just use it rather than recreate it. Besides, if the list may be access by different threads, you have to protect them by a lock before access it.
DEFINE_RAW_SPINLOCK(mylock);
LIST_HEAD(vm_list);
....
my_function() {
....
raw_spin_lock(&kvm_lock);
list_for_each_entry(kvm, &vm_list, vm_list)
*val += *(u32 *)((void *)kvm + offset);
raw_spin_unlock(&kvm_lock);
}
There are a number of places in your sample where you are allocating memory, then immediately leaking the pointer by overwriting it:
head = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
head = newData;
This doesn't make sense. Either your function should be passed in the contents of a linked list entry that it should be adding (e.g, msg and len), or it should treat the value of newData that is being passed in as already having been allocated.
I would strongly recommend that you brush up on your use of linked lists by working some examples in userspace before venturing into the kernel. If nothing else, recovering from errors and performing debugging will be much easier there.
In while loop you have temp instead of temp1 in add_to_end function. Do you really run this code or this mistake is just in this post?
I'm having trouble understanding a piece of C code that represents a linked list structure. The skeleton of the struct looks like this:
struct r{
r *next;
r **prev;
data *d;
}
struct r *rlist;
rlist can be filled by calling the following function: (skeleton only)
r* rcreate(data *d){
struct r *a = xmalloc(sizeof(*r))
a->d = d;
a->next = rlist;
a->prev = &rlist;
if (rlist)
rlist->prev = &a->next;
rlist = a;
return a;
}
How do I go about using this data structure? e.g. how to traverse rlist ?
Edit: here is the function for deleting a node in the linked list
void rdestroy(struct r *a){
if (a->next){
a->next->prev = a->prev;
}
*a->prev = a->next;
destroy(a->d); /* destroy is defined elsewhere */
}
Double prev pointer seems to allow traversing list in one direction only, while allowing easy deletion (because even though you can't access the previous element (easily), you can access the next pointer of previous element, and set it to new correct value when deleting a node.
Without seeing other related functions, it's hard to see why it is done this way. I've not seen this done, and can't immediately think of any really useful benefit.
I think this allows having simpler node deletion code, because node does not need to care if it first or not, because node's prev pointer will always have non-NULL value to a pointer it needs to modify when deleting itself. And same simplicity for insertion before a current node. If these operations are what dominate the use pattern, then this could be seen as minor optimization, I suppose, especially in older CPUs where branches might have been much more expensive.
How to traverse list
This was the question, right? You can only traverse it forward, in a very simple manner, here's a for loop to traverse entire list:
struct r *node;
for (node = rlist ; node ; node = node->next) {
// assert that prev points to pointer, which should point to this node
assert(*(node->prev) == node);
// use node
printf("node at %p with data at %p\n", node, node->d);
}
Example insertion function
This example insertion function demonstrates how insertion before a node needs no branches (untested):
struct r *rinsert(struct r *nextnode, data *d) {
// create and initialize new node
struct r *newnode = xmalloc(sizeof(struct r));
newnode->d = d;
newnode->next = nextnode;
newnode->prev = nextnode->prev;
// set next pointer of preceding node (or rlist) to point to newnode
*(newnode->prev) = newnode;
// set prev pointer of nextnode to point to next pointer of newnode
nextnode->prev = &(newnode->next);
return newnode;
}
There's no good reason to have r ** next in that structure. It's for a double linked list.
So if this thing is created you have it assigned
thisList = rcreate("my data")
now you could start with traversing it
while (thisList->next)
thisList = thisList->next.
...
Your code has many syntactical errors in it, probably because (as you say) it is a "skeleton," so it is hard to parse what the author (whether it was you or someone else) actually intended this code to do.
A simple (doubly) linked list structure looks like this:
struct node {
struct node *next, *prev; // pointers to the adjacent list entries
int data; // use whatever datatype you want
};
struct node *list = NULL; // the list starts empty
void add_entry(int new_data) {
struct node *new_entry = malloc(sizeof(struct node));
// note that in the above line you need sizeof the whole struct, not a pointer
new_entry->data = new_data;
new_entry->next = list; // will be added to the beginning of the list
new_entry->prev = NULL; // no entries currently front of this one
// in general a NULL pointer denotes an end (front or back) of the list
list->prev = new_entry;
list = new_entry; // now list points to this entry
// also, this entry's "next" pointer points to what used to
// be the start of the list
}
Edit: I'll say that if you want us to help you understand some code that is part of a larger program, that you did not write and can't modify, then please post the relevant code in a format that is at least syntactical. As others have said, for example, the use of prev in the code you posted is indecipherable, and it isn't clear (because there are other similarly confusing syntactical problems) whether that was in the original code or whether it is an error introduced in transcription.
Yang, I am not sure how comfortable you are with pointers in general. I suggest taking a look at few other linked-list implementations, it might just do the trick.
Take at look at this Generic Linked List Implementation.