So I have a linked list set up like this:
#define MAX 20
//structure for a single linked list
typedef struct element {
int info;
struct element *link;
} Tnode;
//structure for a grapgh
typedef struct graphAdjList {
int nodes;
Tnode *adjList[MAX];
} Tgraph;
In my code I have it set up like this:
Tgraph *graph;
graph = (Tgraph*) malloc(sizeof(Tgraph));
graph -> nodes = 0;
for(i; i < 20; i++){
graph->adjList[i]= NULL;
}
graph->adjList[2]->info = 222;
Now if I compile this I get an access violation on this last line. Is it that I have not reserved memory for the Tnode part of the struct or am I missing something. How can I initialize the array so that I can assign a value to info in any element of the array?
Thank you
Jason
You are right, the issue is that you have not allocated memory for the individual nodes in adjList.
When you do graph->adjList[2]->info = 222;, graph->adjList[2] is still NULL from the for loop right before it.
To fix this, you need to first allocate memory for it like so:
graph->adjList[2] = malloc(sizeof(TNode));
Note: You could just replace graph->adjList[i] = NULL; with graph->adjList[i] = malloc(sizeof(Tnode)); in the for loop, but allocating as you go can be useful for memory efficiency.
You need to replace
graph->adjList[i]= NULL;
to
graph->adjList[i] = (Tnode*)malloc(sizeof(Tnode));
Related
I have the following Hash_table and Hash_bucket structs
typedef struct Hash_Table{
struct Bucket** bucket;
}Table;
typedef struct Bucket{
struct Bucket* next;
int num;
}Bucket;
I want to allocate 5 Hash Tables which i do like this,
Table** hash_tables = malloc(sizeof(Table*)* 5);
for(int i = 0; i <=4 ; i++){
hash_tables[i] = NULL;
}
To my knowledge, what I have done up to here is correct, and I want to proceed allocating the Hash Tables in my code. As i did with the double pointer above, my allocation for the Hash Table
hash_table[0] = malloc(sizeof(Table));
hash_table[0]->bucket = malloc(sizeof(Bucket*)*10); /* line 2 that is problematic*/
I allocate the size for a Hash_Table and then 10 Hash_Bucket pointers. However, I am having leaks and NOT because I free the memory wrongly. The line 2 of the allocation seems to be redundant (?) and if I replace the Hash_Table with
typedef struct Hash_Table{
struct Bucket* bucket[10];
}Table;
, then the line 2 is not needed, everything works perfect and memory is free'd. I really am clueless as to what I am doing wrong. I've found the mistake, but don't see the mistake in the first place. Thank you all.
The Code you posted without the "line 2 is redundant" part should look like this right:
typedef struct Bucket {
struct Bucket* next;
int num;
} Bucket;
typedef struct Hash_Table {
struct Bucket** bucket;
} Table;
int main(void)
{
// Create hashtable
Table** hash_tables = malloc(sizeof(Table*) * 5);
for (int i = 0; i <= 4; i++) {
hash_tables[i] = NULL;
}
// Create Bucket
hash_tables[0] = malloc(sizeof(Table));
hash_tables[0]->bucket = malloc(sizeof(Bucket*)*10); /* line 2 that is problematic*/
free(hash_tables[0]->bucket);
free(hash_tables[0]);
free(hash_tables);
return 0;
}
If you add the right free's at the bottom you shouldn't have memory leaks.
At least Valgrind says so.
Note: for every written malloc in your code, you need at least 1 free
I am having a problem accessing an subarray of a node. I have two structs written where one contains the other. I'm not able to access the beyond the first node of the subarray.
struct node{
int distance;
int destination;
int weight;
node *adj;
};
struct adjList{
struct node *node;
adjList *array;
};// adjList a is made out of an array of "nodes". Essentially each element in the adjList a should have a pointer to a subarray of "nodes" that i can access.
a=(adjList*) malloc(numOfNodes * sizeof(struct adjList));//allocate space for array of linked lists
for(int j=0; j<numOfNodes; j++){
array[j].node=malloc(numOfEdges * sizeof(struct node));//allocate space for each linked list in the array
}
for(int j=0; j<numOfNodes; j++){
a[j].node->adj[j]=NULL; //trying to set the "jth's" element of the adjacencylist's "jth" node. This syntax does not work as the compiler wont let me even use it.
}
My whole goal here is to have an array of linked lists. Not sure why this method isnt working.
To have array of linked list, you need to create an array of pointers to the first node of linked lists.
struct node **array = malloc(sizeof(struct node*) * arraySize /* numOfNodes */);
Now array[i] will be pointing to ith linked list.
for(int i=0; i<arraySize ; i++){
struct node *head = NULL;
/* Allocate nodes for ith linked list */
for(int j=0; j<numOfNodes; j++) {
if(0 == j) {
array[i] = malloc(sizeof(struct node)); //First node of ith linked list
memset(array[i], 0, sizeof(struct node)); //OR you can use calloc. Required to remove junk pointers in node.
head = array[i];
} else {
head->adj = malloc(sizeof(struct node)); /* Allocate jth node */
memset(head->adj, 0, sizeof(struct node)); //OR you can use calloc. Required to remove junk pointers in node.
head = head->adj;
}
}
}
You can traverse ith linked list as below.
struct node *head = array[i];
while(head) {
printf("\ndist %d dest %d weight %d\n", head->distance, head->destination, head->weight);
head = head->adj;
}
You should read the man page malloc(3), in particular the calloc() part.
It is not enough to just put a pointer into a struct and assume that magically there will be an array. You have to reserve memory for it by using the functions described in that man page. And more importantly you have to free() the reserved memory, when you don't need it anymore.
Also you should consider making the length of your array part of your struct.
Like so:
struct node{
int distance;
int destination;
int weight;
node *adj;
size_t adj_count;
};
struct adjList{
struct node *node;
size_t node_count;
adjList *next; // I renamed this member to next,
// which makes it more clear that this is a linked list
};
EDIT: After you edited your question, there is suddenly a malloc(), but it is most certainly wrong. Or your naming of your data structures is very misleading.
I have created a struct like this
struct PCB
{
int used;
char PID[1];
struct RCB *Other_Resources;
char type[10];
struct PCB **list;
struct PCB *parent;
struct PCB *children;
struct PCB *next;
int priority;
};
then I declared an array of struct PCB * like this
struct PCB *PCBLIST[1024];
my question is do I need to malloc the array of struct pointers in order to use those pointers? I read on another question on here that I should do something like this:
PCBLIST = malloc(1024 * sizeof(struct PCB *));
this is modified slightly, I think in the original question they used MAX instead of giving the actual value like I did 1024.
The error I am getting from gcc c99 is:
error: assignment to expression with array type
but if I try to access an individual struct pointer like with PCBLIST[i]->used I get a seg fault. Can someone shed some light on what I am doing wrong?
You don't need to dynamically allocate the array as that is already allocated by the declaration of the array. You need to allocate struct memory for each of the array entries to point to. Something like:
int ix;
for (ix = 0; ix < sizeof(PCBLIST) / sizeof(PCBLIST[0]); ix++) {
PCBLIST[ix] = malloc(sizeof(struct PCB));
}
Note that that allocates memory for all the entries of the array. If all the entries are always used then a simpler way would be to use a static allocation by declaring the array as an array of structs rather than an array of pointers to those structs:
struct PCB PCBLIST[1024];
That simplies things by not requiring dynamic allocation. But at the cost of potentially using more memory as it does not allow for a sparsely populated array (not all entries allocated). Which one is best to use depends on how you intend to use the array.
PCBLIST should be a pointer, not an array, because you want to allocate space with malloc, and store the address to a pointer.
and you need to allocate the size of the struct and not the size of the pointer.
struct PCB *PCBLIST;
PCBLIST = malloc(1024 * sizeof(struct PCB));
edit: using malloc is matter of choice and not a must
Here are some examples of doing it with static nodes that are not dynamically allocated.
In the first one I don't change the bits you defined in your question (so you do have an array of pointers to PCB objects - I don't think the is what you were after though because the used flag is not useful if you only create the nodes you use:
#include <string.h> // strcpy
// the PCB structure definition
struct PCB
{
int used;
char PID[1];
struct RCB *Other_Resources;
char type[10];
struct PCB **list;
struct PCB *parent;
struct PCB *children;
struct PCB *next;
int priority;
};
// an uninitialized array of pointers to PCB structures
struct PCB *PCBLIST[1024];
// make some PCB objects
struct PCB pcbParent;
struct PCB pcbChild1;
struct PCB pcbChild2;
int main(void)
{
// initialize PCBLIST
for (int i = 0;i < 1024;i++)
PCBLIST[i] = NULL;
// initialize parent
pcbParent.used = 1;
pcbParent.PID[0] = 0;
pcbParent.Other_Resources = NULL;
strcpy(pcbParent.type,"Parent");
pcbParent.list = PCBLIST;
pcbParent.parent = NULL; // no parent
pcbParent.children = &pcbChild1;
pcbParent.next = NULL; // no next sibling
pcbParent.priority = 0;
PCBLIST[0] = &pcbParent;
// initialize child1
pcbChild1.used = 1;
pcbChild1.PID[0] = 1;
pcbChild1.Other_Resources = NULL;
strcpy(pcbChild1.type,"Child");
pcbChild1.list = PCBLIST;
pcbChild1.parent = &pcbParent;
pcbChild1.children = NULL; // no children
pcbChild1.next = &pcbChild2; // next sibling
pcbChild1.priority = 0;
PCBLIST[1] = &pcbChild1;
// initialize child2
pcbChild2.used = 1;
pcbChild2.PID[0] = 2;
pcbChild2.Other_Resources = NULL;
strcpy(pcbChild2.type,"Child");
pcbChild2.list = PCBLIST;
pcbChild2.parent = &pcbParent;
pcbChild2.children = NULL; // no children
pcbChild2.next = NULL; // no next sibling
pcbChild2.priority = 0;
PCBLIST[2] = &pcbChild2;
// do some stuff with the nodes
return 0;
}
It doesn't make much sense to do it that way because you might as well make an array of PCB objects directly - in that case you don't need PCBLIST at all because the list is the array of PCB objects themselves. for example this one makes more sense:
#include <string.h> // strcpy
// the PCB structure definition
struct PCB
{
int used;
char PID[1];
struct RCB *Other_Resources;
char type[10];
struct PCB *list;
struct PCB *parent;
struct PCB *children;
struct PCB *next;
int priority;
};
// an uninitialized array of PCB structures
struct PCB PCBLIST[1024];
int main(void)
{
// initialize PCBLIST
for (int i = 0;i < 1024;i++)
{
PCBLIST[i].used = 0;
PCBLIST[i].Other_Resources = NULL;
PCBLIST[i].list = PCBLIST;
PCBLIST[i].parent = NULL; // no parent by default
PCBLIST[i].children = NULL; // no children by default
PCBLIST[i].next = NULL; // no next sibling by default
}
// initialize parent
PCBLIST[0].used = 1;
PCBLIST[0].PID[0] = 0;
strcpy(PCBLIST[0].type,"Parent");
PCBLIST[0].children = &PCBLIST[1];
PCBLIST[0].priority = 0;
// initialize child1
PCBLIST[1].used = 1;
PCBLIST[1].PID[0] = 1;
strcpy(PCBLIST[1].type,"Child");
PCBLIST[1].parent = &PCBLIST[0];
PCBLIST[1].next = &PCBLIST[2]; // next sibling
PCBLIST[1].priority = 0;
// initialize child2
PCBLIST[2].used = 1;
PCBLIST[2].PID[0] = 2;
strcpy(PCBLIST[2].type,"Child");
PCBLIST[2].parent = &PCBLIST[0];
PCBLIST[2].priority = 0;
// do some stuff with the nodes
return 0;
}
No, you don't need malloc(). You could initialize the pointers to point to static instances of the structs. If you do use dynamic allocation, you should use calloc(), not malloc() plus arithmetic.
I'm reading an algorithms book and I found myself stuck on this bit. I create a doubly linked list and when I try to print out its contents it prints out what I believe is address or some other value that is not relevant to what I want. Here is the code:
typedef struct double_element *dElement;
struct double_element
{
int value;
dElement prev;
dElement next;
};
dElement createNewDListWithElements(int count)
{
dElement element = malloc(sizeof(dElement));
element->value = 1;
element->next = NULL;
element->prev = NULL;
dElement previous = element;
for (int i = 1; i < count; i++) {
dElement el = malloc(sizeof(dElement));
el->value = i;
el->next = NULL;
el->prev = previous;
previous->next = el;
previous = el;
}
return element;
}
void printDList(dElement node)
{
printf("printing doubly linked list:\n");
while (node) {
printf("%i\n", node->value);
node = node->next;
}
printf("end printing double linked list\n");
}
Here is the output:
printing doubly linked list:
1
1070320
1070336
1070352
1070368
1070384
1070400
1070416
1070432
1070448
end printing double linked list
Your problem is that you are trying to allocate space for a struct double_element, but you only ask for enough space to store a struct double_element*.
The problem is that you are allocating space for a pointer instead of the struct itself, the reason the dangerous typedef of the pointer, if you want to guarantee the allocation is correct regardless of the typedef's in your code you can do this
dElement element = malloc(sizeof(*element));
that would allocate space for the struct, just as if you had called
dElement element = malloc(sizeof(struct double_element));
you can see that the typedef is harmful, a pointer should be explicitly a pointer, so the correct way to write the code without falling in this kind of issue is
struct double_element *element = malloc(sizeof(struct double_element));
/* ^ don't skip this no matter what */
also, you should make clear what the struct names are and how you name your variables, you could for example use CamelCase for the struct names, and lower case with underscores for your variables, something like this
struct DoubleElement *element = ...
it would make it clear that DoubleElement is the name of a struct, and even though you can leave the struct instead of tyepdefing it, because that makes it even clearer.
I have strange problem with allocating a linked list in a loop.
Consider a simplified source code :
struct main_s {
minor_s minor_structure; (inline)
};
struct minor_s {
list_s *first_dir;
};
struct list_s {
anotherlist_s *first_object;
list_s *next;
};
struct anotherlist_s {
//multiple fields
};
And i have a basic init/deinit functions like :
struct main_s *main_s_init();
void main_s_deinit();
And now i'm kinda riddled with allocating in loop :
im passing to this function main_s->minor_structure.first_dir and, how_many parameter, defining how many linked nodes going to be initiated.
void loop_inittiation(struct list_s *list, int how_many) {
int i;
struct list_s *tmp = list;
for(i = 0; i < how_many; i++) {
tmp = malloc(sizeof(struct list_s));
tmp = tmp->next;
}
}
And this is where i have problem, im allocating the temporary "tmp" instead of the pointed structure. I understand that to allocate a pointer by tmp u have to use double pointer, but it still doesnt work. What am i missing? In gdb there is no memory space allocated :/.
Do i have to use **tmp?
You've got the right idea about what's wrong. The local copy of tmp in the function is changed, but once you're outside, that value is lost. If you want to change a variable inside a different function in C, you MUST pass the address of the thing you want to change. If the thing you want to change is already a pointer, you must pass the address of the pointer (or double pointer). If it's a double pointer you want to change, then you have to pass a triple pointer. If it's a 123141 pointer, you have to pass a 123142 pointer :)
Change the parameter to the function to:
&(main_s->minor_structure.first_dir)
Just change the input parameter to
struct list **list
change tmp to a double pointer to match it, then each time you use tmp, make sure to throw in an extra dereference..
struct list_s **tmp = list
and
*tmp = malloc(sizeof(struct list_s));
*tmp = (*tmp)->next;
So it would look like:
void loop_inittiation(struct list_s **list, int how_many) {
int i;
struct list_s **tmp = list;
for(i = 0; i < how_many; i++) {
*tmp = malloc(sizeof(struct list_s));
tmp = &((**tmp)->next);
}
}
Another way to do it is to leave the tmp stuff alone, as a single pointer, store the first node you allocate, and then just say
*list = tmp;
But then you do have to treat that first allocation as a special case.