How do I create multiple instances of a struct using a function? - c

I need to create unique instances of a struct and return its address without using malloc.
The problem is everytime I call the function that creates the struct instance, the address to the instance is the same.
inside of List.h
typedef struct List_s List;
struct List_s{
Node* next;
};
inside of List.c
List* List_Create(){
static List head;
printf("%p\n", &head); <--- In both function calls prints out the same address
return NULL;
}
int main(void){
List_Create();
List_Create(); // I
}
I have tried not using the static keyword but the same problem occurs. Additionally, I have put initialized the List struct outside of the function and no problem occurs, but I need to do it inside of a function.

This is a very simple implementation that uses a fixed-size static array, and returns a pointer to an element of it.
List* List_Create(){
static List lists[MAX_LISTS];
static int index = 0;
if (index >= MAX_LISTS) {
return NULL;
}
// initialze contents of lists[index] here
return &lists[index++];
}
If you also need to be able to destroy lists to the pool you'll need to make lists a global variable, so it can be used by both List_Create and List_Destroy. And you'll need some way of keeping track of which elements have been destroyed. You could wrap each List in another struct that has an in_use member.

By using static, there is only one instance, with lifetime for the duration of the process.
Without static you are creating an instance with lifetime for the duration of that specific call. Returning an pointer to that instance us invalid, it's memory is available for reuse.
To do that without heap allocation would require a pool of instances. For example:
#define MAX_LISTS 200
List* List_Create( void )
{
static List list_pool[MAX_LISTS] ;
static size_t next_list = 0 ;
List* list = NULL ;
if( next_list < MAX_LISTS )
{
list = &list_pool[next_list] ;
}
return list ;
}
The above is a very crude example, it has no means of returning list to the pool, which may be a requirement. To do that you would need to move the statics outside of the function and have a means of marking an element used/unused, and a means of searching for an unused element on "creation". However the point is that you need a pool, the precise implementation is beyond the scope of this question I think.

Related

C Linked List infinite loop

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.

Why use dynamic memory allocation(i.e. malloc()) when implementing linked list in c?

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

How to free memory allocated to local static pointer

In legacy C code I have one pointer basically an array of size equal to one of enumerator and it is static in local scope. But now I have to remove that enumeration and now this static local array is giving error. I can convert that array to normal pointer and then allocate it dynamically but I am not sure how to do that. Below is sample code I have simplified from existing code base.
enum
{
E1,
E2,
EOL
};
void func
{
//static int array[EOL]; //-> that how it was earlier
static int *array = (int*)malloc(sizeof(int)*EOL); //Will this allocated memory only once
//or on every invokation.
free(array);//will it free the memory more than once?
}
Now I can move array pointer to global scope and then allocate it in main and free it in atexit functions but I want to keep changes minimum as I am not sure of impact it will have in shared projects?
Thanks
The malloc will occure only once.
1) You can use a static boolean to let you know if the pointer in the array variable can be free.
2) You can free the pointer then set it to NULL. The next occuration of the free will do nothing.
If you want to keep changes minimal then simply move the enumeration definition inside the function body before this static variable. Or you can use even an unnamed enum with one enumerator for the size of the array.
I do not understand your attempts to substitute the array for a dynamically allocated array.
Moreover at present C allows to use variable length arrays. So your could define the function such a way that it had a parameter that would specify the size of the local (non-static) array.
You can't initialise a static variable with something non const if you are using C.
If you are using C++, then the static pointer will only get a memory pointer allocated to it once.
I just solved the problem by using one function which basically is collects all memory allocated to local static pointers like above and then other functions free them during the end as it is registered using atexit function.
struct node
{
node *next;
void *content;
};
node* head = NULL, tail =NULL;
void addToList(void* ptr)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
p->next = NULL;
p->conent = ptr;
tail->next = p;
tail = p;
return;
}
void freeList()
{
struct node* p = NULL, p1 = NULL;
for(p = head; p != NULL; p = p->next)
{
free(p1);
free(p->content);
p1 = p;
}
head = tail = NULL;
return;
}
/*
*/
void func
{
//static int array[EOL]; //-> that how it was earlier
static int *array = (int*)malloc(sizeof(int)*EOL); //Will this allocated memory only once
addToList(array); //or on every invokation.
free(array);//will it free the memory more than once?
}
As you can see it above code a linked list is created in separate .c file and using .map method head,tail and node will not be exposed to outside world only addToList and freeList will be visible. In every places just after doing a malloc I am calling addToList and then freeList will free up the memory.
Thanks

Using a function call to implement a stack

I'm a little unclear on this part of C, since it's a bit unlike other languages I've used, but this may just be a dumb question. I'm trying to implement a stack. I have the node struct, it has the information I want to pass:
struct position{
int square[2];
int counter;
struct position *prev;
};
so in main, I declare and initialize the bottom node of the stack, set *prev to NULL, then declare the rest. My question is, what happens when I try to pass it to function pop? I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes? Or should I return the position and set that equal to a new position object in main? What if I decide to create several of these nodes in a function? Will they remain once the function closes?
Edit: mah reminded me of my followup question which is, if they don't exist outside of the function, should I use malloc to create the space in the memory for them?
The lifetime of your objects depend on where they're created; if you declare for example a structure within a block of code (where a block is everything inside { and its matching }), that structure is no longer valid once execution leaves the block. Pointers to that structure are only valid as long as the structure is valid.
For what you're describing, you want to dynamically allocate your structures, using either malloc() or a similar function. Dynamically allocated data will remain valid (assuming you do not overwrite it) until you free() the memory, or until your program terminates. Pointers to these areas of memory will remain valid for that same period of time.
Consider:
static struct position *topOfStack = NULL;
void push(struct position *node)
{
node->prev = topOfStack;
topOfStack = node;
}
struct position *pop()
{
struct position *popped = topOfStack;
if (topOfStack) topOfStack = topOfStack->pref;
return popped;
}
To use this, you can:
f() {
struct position *node = malloc(sizeof(*node));
/* ... fill in node details ... */
push(node);
}
Notice that I allocated the node dynamically. Had I just declared a struct position node;, I could legally call push(&node); but once my function left scope, the stack would have an invalid item in it (which would likely cause havoc).
what happens when I try to pass it to function pop?
it depends on your pop() function prototype. If the pop's function prototype should be:
struct position* pop(struct position* stack);
I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes?
your question is quite unclear, and it looks like a big misunderstanding of instance scoping in C. Basically, you have two ways to allocate variables, either on the stack or on the heap. The scoping you're talking about is stack instances scope.
What if I decide to create several of these nodes in a function? Will they remain once the function closes?
basically, if you use the stack, they will live as long as the scope they're declared in. In C, scope is defined by { and }. for example:
int main() {
struct position pos1;
struct position pos2;
struct position pos3;
pos3.prev = pos2;
pos2.prev = pos1;
pos1.prev = NULL;
pop(&pos3);
}
there you declare 3 variables, and associate them, and the pop function just resets the .prev link. But for a stack that kind of architecture is not really useful, because it is quite limited.
There you definitely need to push your instances in the heap, thus using malloc() and free():
// push() pseudocode:
// take stack, iterate over each prev until prev is NULL
// allocate prev with malloc() the same way as for "stack" in main()
// insert values in prev
void push(struct position* stack, int* value);
// pop() pseudocode:
// take stack, iterate over each prev until prev->prev is NULL,
// then keep prev->prev in a temporary variable
// set prev to NULL
// return temporary variable (former prev->prev)
struct position* pop(struct position* stack);
int main() {
int value[2];
struct position* stack = malloc(sizeof(struct position));
// value is what you want to push to the stack
value[0] = 42;
value[1] = 42;
push(stack, value);
value[0] = 2;
value[1] = 20;
push(stack, value);
struct position* pos;
pos = pop(stack);
// do something with pos->value
free(pos);
}
there you create a pointer to a node for which you allocate some memory in the heap. the push() function is allocating some new memory, assigning .prev for that new space to stack's address and populating that memory with the value. pop() should get to the value before the last one, reset its pointer to that value, and return that value.
Of course, I'm just giving concepts and ideas here, I'm leaving you get to the real implementation. One advice though, instead of using square that contains an array, use two separate values in your struct, that will make it simpler for a first implementation.

c - creating a linked list without malloc

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.

Resources