I'm trying to implement my own version of malloc() function in c.
I decided to keep track of my allocated blocks using a linked list of meta-data objects that would store some information about the allocated chunk and and place it right before the chunk.
Now long story short while debugging I came across the fact that my linked list is behaving very strangely.
here's a piece of the code to help understanding the problem.
typedef struct meta_data
{
size_t size;
int free;
struct meta_data* next;
}meta_data;
meta_data* global_base;
void *mymalloc(size_t size)
{
if(size > 0)
{
meta_data block_meta;
void* pointer = sbrk(size + block_size);
block_meta.size = size;
block_meta.next = NULL;
block_meta.free = 0;
if(!global_base) //first allocation
{
global_base = &block_meta;
}
else
{
block_meta.next = global_base;
}
return pointer;
}
else
{
return NULL;
}
}
I wrote this code which I assume will append a new item to the tail of my global_base (linked list) every time I call mymalloc(<some_size>);
however when I tried to debug and make sure that my linked list is in order by calling mymalloc() couple of times and check is my linked list is being populated properly
void printList()
{
meta_data * node = global_base;
while (node->next != NULL)
{
printf("%zu", node->size);
printf(" -> ");
node = node->next;
}
printf(" \n ");
}
int main()
{
mymalloc(10);
mymalloc(8);
mymalloc(4);
printList();
return 0;
}
I expected my output to be
10 -> 8 -> 4 however it was 4 -> 4 -> 4 -> 4 -> 4 ..... and goes into an infinite loop
any idea where am I going wrong with this code.
I'm a little new to programming with C so my only guess is that I'm making use of reference & and pointer * improperly.
furthermore I have seen tones of code where the assignment of struct's attribute is happening with the use of -> but I could only use . to make it (could this be the problem anyhow)?
help is appreciated thanks guys
There are multiple problems with your approach:
the meta_data block_meta; is a local variable. You cannot use that to link the blocks. Local variables are reclaimed when the function exits. You should use global memory retrieved from the system with sbrk, pointed to by pointer.
the print loop is incorrect: you should write while (node != NULL) to print all blocks.
Your code has dozens of issues which I will address.
Now the problem with your code, in fact the biggest issue with it is that the myalloc function doesn't create a new block_meta node. It just declares a block_meta variable (which will end up on the stack and even worse is a recipe for disastrous bugs I believe the infinite loop is a result of this). You should you use the sbrk function to create a meta_data node before doing anything like so:
...
meta_data *block_meta = sbrk(sizeof(meta_data));
block_meta->size = size;
block_meta->next = NULL;
block_meta->free = 0;
if(!global_base)
{
global_base = block_meta;
}
The myalloc function checks to see if global_base has been assigned, that is if there is a root node in the linked list. If there is one it should simply tell the current variable to link itself to the global_base that is point it's next variable at global_base, this is a big error. Firstly, the global_base is the root node and it makes no sense to tell the current node to link itself to the root of the linked list, it's supposed to link itself to the next node not the root. Secondly, the reference to the previous node is lost which means it's not a linked list anymore. A proper solution would be saving the current node in a variable using a static variable which prevents it from getting lost when the myalloc function exits:
...
static meta_data *curr;
then right before returning the pointer to the newly allocated block you add this line to hold the node that had been newly created:
...
curr = block_meta;
return pointer;
now return to the erring else statement and change that to to ensure that the previous node points to the current node:
...
else
{
curr->next = block_meta;
}
Related
I have a function called addMod that, when called, adds a node to a certain index of an array of Module struct LinkedLists called modules contained within a System struct. A Module struct has a string field, two int fields, and a pointer to the next Module, the first three fields being initialized according to arguments provided in addMod. addMod roughly looks like this:
int addMod(System *system, const char *text, int num1, int num2, int index) {
Module *temp = malloc(sizeof(Module));
Module *current;
temp->next = NULL;
if ([any of the constructors are invalid]) return 0;
temp->text = malloc(strlen(text)+1);
strcpy(temp->text, text);
temp->num1 = num1; temp->num2 = num2;
if (!system->modules[index]) {
system->modules[index] = temp; //If there are no modules in the LinkedList at the given index, makes the head = temp.
}
else {
if (system->compare(temp, system->modules[index]) <= 0) { //compare is a func pointer field of system that compares two Modules to see in what order they should be. Here, we check if temp should become the head of modules[index].
temp->next = system->modules[index]; //Assigns the current head as the module following temp.
system->modules[index] = temp; //Makes temp the current head.
}
else {
current = system->modules[index];
while (current->next && system->compare(temp, current->next) > 0) { //While current isn't the last node in the LinkedList and temp comes after the node after current
current = current->next;
}
temp->next = current->next; //Adds temp in between current and current->next.
current->next = temp;
}
}
return 1;
}
All of the above works as expected, except when printing the contents of system, the console indicates there's a memory leak that I'm assuming is because I fail to properly free temp based on what valgrind tells me. My problem is not knowing where to free it- it seems anywhere I put it causes a segfault after printing the contents. From my understanding, I have to make sure that no other variables are depending upon the value being held by temp, but I can't seem to find a way to do that considering every possible ending of my if statement leads to assigning temp to a node within modules. Putting free(temp) between the logic and return 1 also yields a segfault, I'm assuming because I often malloc temp again when calling addMod multiple times in succession.
In summary, to add a new node to a LinkedList that may or may not be populated, in which this new node may be inserted in any arbitrary position in the LinkedList, I have to allocate memory to a temporary node so that I can insert it later. Where do I free this allocated memory once I have successfully inserted the node?
Assuming your management of a System instance is sound (a big assumption, since I cannot see that code), you have giant hole in the memory allocation of temp with a subsequent hard return 0 in the condition where the "constructor" check fails. More to the point:
Module *temp = malloc(sizeof(Module)); // memory allocated here...
Module *current;
temp->next = NULL;
if ([any of the constructors are invalid])
return 0; // and leaked here.
It may be as simple as swapping the check around. Obviously other code that is supposed to free the dynamic allocations should be considered and evaluated as well.
A Simpler Approach
The node addition code is complicated and it need not be. In the end all you should really care about is finding the place where your new node resides.
If the slot in the table is empty, its the first node in that list.
IF the slot in the table is NOT empty, find the sorted location and insert it there.
Both of those can be accomplished with a single while-loop by using a pointer-to-pointer, where said entity hold the address of the pointer that will hold the new node in either of the cases above, and as a bonus, surgical insertion is literally two assignments.
It's done like this. Note that most of this code is just making the Module object safely. The actual insertion is only a single while-loop and some pointer assignments. It assumes the table in System initially contains NULL entries:
int addMod(System *system, const char *text, int num1, int num2, int index)
{
// allocate new node here
Module *temp = malloc(sizeof *temp);
if (temp == NULL)
{
perror("Failed to allocate new Module");
return 0;
}
size_t len = strlen(text);
temp->text = malloc(len + 1);
if (temp->text == NULL)
{
perror("Failed to allocate module name");
free(temp);
return 0;
}
// finish copying member data
memcpy(temp->text, text, len);
temp->text[len] = 0;
temp->num1 = num1;
temp->num2 = num2;
// now find where it belongs, and set next appropriately
Module **pp = system->modules + index;
while (*pp && system->compare(temp, *pp) <= 0)
pp = &(*pp)->next;
temp->next = *pp;
*pp = temp;
return 1;
}
Understand this is from deriving what I think your System type looks like, as it was never presented:
typedef struct System
{
Module *modules[MAX_MODULES];
int (*compare)(const Module* lhs, const Module *rhs);
} System;
I'm fairly confident it is similar to this. Of course, you'll have to adapt if it isn't. I suggest you review this and step through it in a debugger. There is no substitute for watching it live.
Best of luck.
I am trying to edit part of a backnet stack to not use malloc as it always fails. The code uses malloc to create an object and insert into a linked list. In the following code snippet I have commented out the malloc. My plan is to create a local instance of the struct and insert that into my list. I am able to insert 2 items into my list, when trying to add the third, the list is not properly terminated and I enter an infinite while loop. Can anyone see why my list is not properly terminated?
CHobjects is a stuct and I want a linked list of them. I can not use malloc to create new CHobject instances. To get around this I am attempting to create a local instance of CHobject and add that to my list.
CHobjects* newNode(instance, channel, name, description)
{
CHobjects *node;
CHobjects newNode;
node=CHobjects;
while(node!=NULL)
{
if(node->instance==instance)
return
node=node->next;
}
if(strlen((char *)objectName)>objectNameMax || strlen((char *)description)>descriptionMax)
goto cc8; //fail name or description is too long
// if((node=(CHobject *)malloc(sizeof(CHobject)))==NULL) //get a block of space for this object's info
// goto cc8; //fail if we can't get space for it
test.next=CHobjects; //link on to list
CHobjects=&test;
CHcount++;
}
This code simply adds the elements to the list, the whole code would afterwards set some variables to default values.
After our extensive discussion in the comments, I think it's obvious that you problem is the use of local struct instances in a global list. The structs you create on the stack become invalid on exiting the newNode() function, and the same stack space is recycled on the next call. So you link the same instance to itself, and after two calls, you've got a circular list, and enter an infinite loop.
Since you're obviously on plain C without a heap, your only chance is to roll your own struct allocator in global memory, preallocated at compile time. Declare a global array of CHobjects large enough to satisfy all of you allocations (i.e. the maximum length of the list). In your case, this seems to be 4. Here's a raw outline:
#define CHOBJECTS_MAX 4
static CHobjects gaCHobjects [CHOBJECTS_MAX];
static int giNextSlot = 0;
public: static CHobjects* Allocator ()
{
return gaCHObjects + giNextSlot++;
}
The function Allocator() returns a struct pointer from your global array and increments the giNextSlot index, so you get a new instance on each invocation. Use this pointer inside newNode() instead of a local CHobjects instance.
Your question is a little unclear, but I think that it's possible to give you a useful answer anyway.
The only way I can think that you can implement this is using an array as the storage for the linked list, and as a plus you will have both an array and a linked list at the same time
#include <stdio.h>
struct list {
int value;
struct list *next;
};
static void
print_list(const struct list *item)
{
while (item->next != NULL) {
fprintf(stdout, "%d\n", item->value);
item = item->next;
}
}
int
main(void)
{
struct list items[15];
size_t count;
count = sizeof items / sizeof *items - 1;
for (int index = 0; index < count; ++index) {
items[index].next = &items[index + 1];
items[index].value = index + 1;
}
items[count].next = NULL;
print_list(items);
}
As you see, you need access to the given array element to use as storage location, and the array must be valid through the life time of the linked list.
I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.
I declared a linked list implemented in C as follows:
struct node_List {
int i;
char * name;
struct node_List* next;
};
typedef struct node_List nodeList;
Then I declared the list head globally as:
nodeList list; // head of the list - does not contain relevant data
Finally, I have a function id(char * s) with a string s as th only argument.
nodeType id(char *s)
{
nodeType *p; // another List type
if ((p = malloc(sizeof(nodeType))) == NULL) {
// error: out of memory;
}
nodeList * node = &list;
// printf(" ");
while (node->next != NULL){
node = node->next;
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
}
// error: not found;
}
The problem is, when i run this program and call foo("somestring") the program executes the error: not found part and aborts execution, despite the string somestring being in the list.
I tried executing the very same program by inserting some printf() for debugging purposes, and it works perfectly, except it prints additional characters along with the output.
This happens each time I add some print lines, e.g. if I uncomment the two printf()s which I wrote in the example above (one of them or both, i get the same successful result). It doesn't work though if the printf is called with no arguments or with an empty string "".
I can't figure out what's happening, I double-checked the list creation and population functions and I am totally sure they work correctly. I tried changing the while break condition, but that didn't work, too. I have observed a similar behaviour on both Linux (with gcc) and Windows (using CodeBlocks editor's integrated compiler)
How could a printf directive affect a program so much?
EDIT: This code is part of a syntax analyzer written in Yacc. The whole code can be found below. It's a long read, and it is not completed, but the code above was tested and used to work as explained.
lexer: http://pastebin.com/1TEzzHie
parser: http://pastebin.com/vwCtMhX4
When looking in the provided source code, the algorithm to explore the linked list has two ways to miss node in the while-loop comparison.
Way 1 - starting only from the second node of the list.
Placing node = node->next; before the comparison will force the first comparison to be &(list)->next instead of &(list).
To start from the first node, simply place node = node->next; after
the comparison.
Way 2 - never ending to the last node of the list.
Using (node->next != NULL) in the while condition will force to exit from the loop before comparing the last node => node->next = NULL;.
To end by the last node, simply change the while condition to (node != NULL).
Solution:
while (node != NULL){ // end from the last node
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
node = node->next; // explore link after comparison
}
The actual error is a wrong type declaration of a variable returned by the function:
nodeType* createPoint(char* l){
nodeList* p;
if((p=malloc(sizeof(nodeList))) == NULL){
yyerror("out of memory");
} else {
// do stuff with p
}
return p;
}
The function return value was a nodeType* and p was instantiated as nodeList*.
The declaration of those two types was pretty simple, that's why the program could work.
the working code can be found here.
The strange behaviour with printf() was probably caused by the heap space needed for printf's arguments: since this function accepts an arbitrary number of parameters, it saves them in a list. This list is instantiated in the heap, there overwriting the old data left there from the wrong implementation of createPoint.
in order to create a linked list(which will contain an attribute of next and previous node),i will be using pointers for the 2 next and previous nodes,yet i was wondering if i could complete the code without using malloc(allocating memory):
for example:
instead of malloc-ing:
link *const l = (link *)malloc(sizeof(link));
if(l == NULL)
/* Handle allocation failure. */
...
l->data = d;
l->next = list->head;
head = l;
can i simply create a new link variable with the attributes formatted(value,pointer to next and previous link),and simply link the last link in my last link in the chain to this one?
my list file is b,for example.
link i;
i.date=d;
getlast(b).next=&i
i appologize ahead for the fact i am new to c,and will be more than glad to receive an honest solution :D
edit:
i tried using malloc to solve the matter.i will be glad if anyone could sort out my error in the code,as i can not seem to find it.
#include <stdio.h>
#include <malloc.h>
struct Node{
int value;
struct Node * Next;
struct Node * Previous;
};
typedef struct Node Node;
struct List{
int Count;
int Total;
Node * First;
Node * Last;
};
typedef struct List List;
List Create();
void Add(List a,int value);
void Remove(List a,Node * b);
List Create()
{
List a;
a.Count=0;
return a;
}
void Add(List a,int value)
{
Node * b = (Node *)malloc(sizeof(Node));
if(b==NULL)
printf("Memory allocation error \n");
b->value=value;
if(a.Count==0)
{
b->Next=NULL;
b->Previous=NULL;
a.First=b;
}
else
{
b->Next=NULL;
b->Previous=a.Last;
a.Last->Next=b;
}
++a.Count;
a.Total+=value;
a.Last=b;
}
void Remove(List a,Node * b)
{
if(a.Count>1)
{
if(a.Last==b)
{
b->Previous->Next=NULL;
}
else
{
b->Previous->Next=b->Next;
b->Next->Previous=b->Previous;
}
}
free(b);
}
Yes - you can do that.
e.g.
link l1,l2;
l1.next = &l2;
l2.next = NULL;
Is a perfectly fine and valid linked list of 2 nodes.
You could also create a bunch of nodes, and link them together based on your needs, e.g. create a linked list of the argv:
int main(int argc, char *argv[])
int i;
link links[100];
for (i = 0; i < argc && i < 100; i++) {
//assuming the nodes can hold a char*
links[i].data = argv[i];
links[i].next = NULL;
if (i > 0)
links[i-1].next = &links[i];
}
There are of course some drawbacks:
The number of nodes is determined at compile time in these examples. (in the last example one could malloc a buffer for argc
nodes instead of hardcoding 100 though)
The lifetime of these nodes are the scope they are declared in, they no longer exists when the scope ends.
So you cannot do something like this:
void append_link(link *n, char *data)
{
link new_link;
n->next = &new_link;
new_link.next = NULL;
new_link.data = data;
}
That is invalid, since when append_link ends, the new_link is gone. And the passed in n->next now points to a local variable that is invalid. If new_link instead was malloc'ed, it will live beyond this function - and all is ok.
Not really.
You could create a variable for each and every node in your list, but what happens when you want another node? Fifty more nodes? These variables also won't hang around after you've left the scope they were defined in, which means you'd either have to make everything global or use static storage and expose a pointer to them. This means that all pointers to them after that scope will be invalid. These are both very ugly solutions.
If you don't understand what I mean by scope, here's a quick example:
int main() { /* Entering function scope. */
int x = 5;
{ /* Entering block scope. */
int y = 7;
printf("%d\n", y);
} /* Exiting block scope, all variables of this scope are gone. (y) */
printf("%d %d\n", x, y); /* Won't compile because y doesn't exist here. */
} /* Exiting function scope, all non-static storage variables are gone. (x)
You could also create a global array, thinking that this gets around having a lot of different variables, but if your solution is to implement this using an array, why are you using a linked list and not an array? You've lost the benefits of a linked list by this point.
There are only two ways in C to create in-memory data structures that don't have a fixed-at-compile-time size:
with allocated storage duration, i.e. via malloc.
with automatic storage duration, which in terms of implementation, means "on the stack", either using variable-length arrays or recursion (so that you get a new instance at each level of recursion).
The latter (automatic storage) has the property that its lifetime ends when execution of the block where it's declared terminates, so it's difficult to use for long-lived data. There's also typically a bound on the amount of such storage you can obtain, and no way to detect when you've exceeded that bound (typically this results in a crash or memory corruption). So from a practical standpoint, malloc is the only way to make runtime-dynamic-sized data structures.
Note that in cases where your linked list does not need to have dynamic size (i.e. it's of fixed or bounded size) you can use static storage duration for it, too.
Memory for new nodes has to come from somwhere. You can certainly create individual variables and link them manually:
link a, b, c;
...
a.next = &b;
b.next = &c;
c.next = NULL;
As you can imagine, this approach doesn't scale; if you want more than 3 elements in your list, you'd have to allocate more than 3 link variables. Note that the following won't work:
void addToList( link *b )
{
link new;
...
b->next = &new;
}
because new ceases to exist when the addToList exits, so that pointer is no longer meaningful1.
What you can do is use an array of link as your "heap", and allocate from that array. You'll need to keep track of which elements are available for use; an easy way of doing that is initializing the array so that each a[i] points to a[i+1] (except for the last element, which points to NULL), then have a pointer which points to the first available element. Something like the following:
// You really want your "heap" to have static storage duration
static link a[HEAP_SIZE];
// Initialize the "heap"
for ( size_t i = 0; i < SIZE - 1; i++ )
a[i].next = &a[i+1];
a[i].next = NULL;
// Set up the freeList pointer; points to the first available element in a
link *freeList = &a[0];
// Get an element from the "heap"
link *newNode = freeList;
freeList = freeList->next;
newNode->next = NULL;
// Add a node back to the "heap" when you're done with it:
deletedNode->next = freeList;
freeList = deletedNode;
Again, you're limited in how many list nodes you can create, but this way you can create a large enough "heap" to satisfy your requirements.
1. Obviously, the phsyical memory location that new occupied still exists, but it's now free for other processes/threads to use, so the value contained in that address will no longer be what you expect.