Error while accessing array of pointers to structures - c

I am trying to make an array of structures in which each array elements itself points to another structure of the same type. In order to better explain the problem, I have made a schematic for it! The names of the variables are according to the code (shown below)
But I am getting an error while I am freeing the memory! Can someone provide some hints for solving this! Thanks.
Error:
tempCodeRunnerFile.c:36:42: error: member reference type 'Vertex *' (aka 'struct Node *') is a pointer; did you mean to use '->'?
Vertex* ptr = (*(vertexarray+ i)).next;
~~~~~~~~~~~~~~~~~~~^
->
tempCodeRunnerFile.c:57:14: warning: incompatible pointer types passing 'Vertex [4]' to parameter of type 'Vertex **' (aka 'struct Node **') [-Wincompatible-pointer-types]
finalize(vertexarray);
^~~~~~~~~~~
tempCodeRunnerFile.c:30:24: note: passing argument to parameter 'vertexarray' here
void finalize(Vertex** vertexarray){ // free the dynamic memmory
^
1 warning and 1 error generated.
Code:
#include <stdio.h>
#include <stdlib.h>
// Data structure to store a linked list node
typedef struct Node
{ int data;
struct Node* next;
}Vertex;
Vertex* initialize(); //Vertex** vertexarray
void finalize(Vertex** vertexarray);
Vertex* initialize(){ // initialise the elements inside the array
Vertex* node = (Vertex*)malloc(sizeof(Vertex));
if(node ==NULL){
printf("Error in initialising"); // If node cannot be created due to memmory issues.
return NULL; // listhead is NULL
}
else{
node->data = -1; // The initial node is empty (contains data value -1, symbolising empty).
node->next = NULL; // The list at the time of initialisation is empty and hence no node to further point on.
}
return node;
}
void finalize(Vertex** vertexarray){ // free the dynamic memmory
int i;
for (i=0; i<4;i++){ // free all the memmory
Vertex* ptr = (*(vertexarray+ i)).next;
Vertex* tmp;
while( ptr!= NULL) // Termination condition: At the end, the pointer is not pointing to any node, but a NULL value
{
tmp = ptr; // make tmp the current node starting from listhead.
ptr = ptr->next; // update the pointer to the next pointer
free(tmp); // free the previous pointer
}
}
}
int main(void)
{
Vertex vertexarray[4];
int i;
for (i=0; i<4;i++){
vertexarray[i].next = initialize();
}
finalize(vertexarray);
return 0;
}

As the finalize method would need to free every element of the array you could write it like this
void finalize(Vertex vertexarray[], size_t len)
{ // free the dynamic memmory
int i;
for (i = 0; i < len; i++)
{ // free all the memmory
Vertex *ptr = vertexarray[i].next;
Vertex *tmp;
while (ptr != NULL) // Termination condition: At the end, the pointer is not pointing to any node, but a NULL value
{
tmp = ptr; // make tmp the current node starting from listhead.
ptr = ptr->next; // update the pointer to the next pointer
free(tmp); // free the previous pointer
}
}
}
And call it in main as
finalize(vertexarray, 4);
It will still work if vertexarray will allocated dynamically as you still need to keep track of how many elements has. Unless you change the vertexarray to also be a list

Related

Why do I get a segmentation fault when trying to create a linked list using structures?

I am writing a code to create a linked list using structures in C language.
I have defined the structure with a data type and a pointer to structure type. Further I have used typedef to typecast this to Node_s.
I am using a function to initialise the first node; which basically won't contain any value but just returns the headpointer, which I will use to point to my next structure (node).
In the main block, I am initialising a structure pointer with Null value and then feeding the value from initialiser function to this pointer.
But this code is returning zsh: segmentation fault . Can someone explain me the issue!
#include <stdio.h>
#include <stdlib.h>
//Node* Initialize;
typedef struct Node {
int data;
struct Node* next;
} Node_s;
Node_s* Initialize(){
Node_s init_node;
Node_s* headlist;
init_node.data = 0;
init_node.next = headlist;
return headlist;
}
int main()
{
Node_s* ptr = NULL;
ptr = Initialize();
// 1st Node
ptr->data = 1;
Node_s* ptr2 = NULL;
ptr->next = ptr2;
// 2nd Node
ptr2->data = 1;
ptr2->next = NULL;
printf(" \n done deal %d", (*ptr2).data );
return 0;
}
main(): the variable ptr is uninitialized as returned from Initialize(). If it points to NULL or any other memory you don't have access to it will segfault when you deference it's members (ptr->data).
main(): the variable ptr2 is initialized to NULL, then you try to dereference it set its members. This will trigger a segfault if you get there.
Initialize(): init_node is a local variable and has no effect outside the function.
Initialize(): headlist is uninitialized as I mentioned above.
Initialize(): I suggest you change the signature to Node_s *Initialize(int data) so you can set the data to the value you need instead of a dummy value.
Here's a better starting point:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node_s;
Node_s *Initialize(int data) {
Node_s *headlist = malloc(sizeof(*headlist));
if(!headlist) {
printf("malloc failed\n");
return NULL;
}
headlist->data = data;
headlist->next = NULL;
printf("done deal %d\n", headlist->data);
return headlist;
}
int main() {
Node_s *ptr = Initialize(1);
if(!ptr)
return 1;
ptr->next = Initialize(2);
if(!ptr->next)
return 1
return 0;
}
The next step would be to eliminate the printf("done deal ...) statement in favor of a function that prints your linked list. Then write a function that frees the linked list. Then write a function that can Append(int data) an element to your list to replace Initialize().

Cannot allocate dynamic array on C

Im trying to create a graph structure on C but I got some issues. First, Im getting 2 compilation errors:
main.c:18:19: error: member reference type 'node' is not a
pointer; did you mean to use '.'?
graph[index]->start = NULL;
~~~~~~~~~~~~^~
.
main.c:18:27: error: expression is not assignable
graph[index]->start = NULL;
~~~~~~~~~~~~~~~~~~~ ^
2 errors generated.
compiler exit status 1
I cannot figure out what Im doing wrong. I tried to create an array of nodes* but the compiler doesn't recognize it as a pointer for some reason. It's like malloc doesn't work. Also, I can't manage to acess edge* fields because it's like the array of nodes* is non-existent.
#include <stdio.h>
#include <stdlib.h>
#define maxNodes 4
typedef struct edge {
int target;
struct edge* next;
} edge;
typedef struct {
edge* start;
} node;
void initializeGraph(node* graph) {
graph = (node *) malloc(maxNodes * sizeof(node));
for(int index = 0; index < maxNodes; index++) {
graph[index]->start = NULL;
}
}
int main(void) {
node test;
initializeGraph(&test);
}
Im trying to initialize my structure. Any help is appreciated.
You have a large number of problems in your short example code. As to your error, that is covered by #dbush's answer and [...] serves as a dereference on your pointer making the '.' (dot) operator proper instead of the -> arrow operator.
Next, you cannot declare a node with static storage duration in main() and pass its address for allocation in your function. When you declare node test; all storage is already provided on the stack. You can't then pass that address to your function and allocate additional memory for that struct.
If you intend to have more than one node, then you can either declare an array with static storage duration in main(), or you must declare a pointer in main() and allocate in your function. To make that allocation visible in main(), as noted in my comment, you can either (1) make the return type node * and return a pointer to the allocated block for assignment in the caller, or (2) make the parameter node** and pass the address of your pointer as the parameter.
Putting that altogether and choosing option (1) above, you could do:
#include <stdio.h>
#include <stdlib.h>
#define maxNodes 4
typedef struct edge {
int target;
struct edge* next;
} edge;
typedef struct {
edge* start;
} node;
node *initializeGraph (void) {
node *graph = malloc(maxNodes * sizeof *graph);
if (!graph)
return NULL;
for (int index = 0; index < maxNodes; index++) {
graph[index].start = NULL;
}
return graph;
}
int main (void) {
node *test = initializeGraph();
if (!test)
fputs ("error: initialization failed.\n", stderr);
else
puts ("initialization succeeded");
}
Example Use/Output
$ ./bin/graphinit
initialization succeeded
Allocating For Each test[i].start
Before you can make use of any of the start pointers, you must allocate storage for a struct edge and assign the beginning address for that block of memory to each of your test[i].start pointers. You can do that in your same initializeGraph() function by allocating where you currently set the pointers NULL, e.g.
node *initializeGraph (void)
{
node *graph = malloc(maxNodes * sizeof *graph);
if (!graph)
return NULL;
for (int index = 0; index < maxNodes; index++) {
graph[index].start = malloc (sizeof *graph[index].start);
if (!graph[index].start)
return NULL;
}
return graph;
}
You can then assign a value to the target in each. Extending the earlier example, you could do:
int main (void) {
node *test = initializeGraph();
if (!test)
fputs ("error: initialization failed.\n", stderr);
else
puts ("initialization succeeded");
for (int i = 0; i < maxNodes; i++)
test[i].start->target = i;
puts ("targets filled");
}
Example Use/Output
$ ./bin/graphinit
initialization succeeded
targets filled
(don't forget to free the memory you allocate when it is no longer needed)
Look things over and let me know if you have further questions.
The array index operator [] implicitly dereferences a pointer. The syntax a[b] is exactly the same as *(a + b).
This means that graph[index] has type node, not node *. So use . instead of -> as the error message suggests.
graph[index].start = NULL;

runtime error: null pointer passed as argument 1, which is declared to never be null

I wrote a program that creates Linkedlists with two values.
It worked when I just had int values in it but now that I added char* this error messages shows
runtime error: null pointer passed as argument 1, which is declared to never be null
As mentioned before this worked fine until I added char* to the constructor and the struct. Not sure where it goes wrong as the error seems to come from different lines in the code everytime I run it... So what do i need to change ?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
typedef struct node {
int val;
char* name;
struct node *next;
} node_t;
void addFirst(int value, char* word, node_t** nd) {
//initialize new node, allocate space, set value
node_t * tmp;
tmp = malloc(sizeof(node_t));
tmp->val = value;
strcpy(tmp->name, word);
//let the new nodes next pointer point to the old head
tmp->next = *nd;
//Make tmp the head node
*nd = tmp;
}
int findItem(int value,char* word, node_t *nd) {
if(nd->val == value)
return 0;
while(nd->next != NULL) {
if(nd->val == value && strcmp(word, nd->name) == 0)
return 0;
if(nd->next != NULL)
nd = nd->next;
}
return -1;
}
int main (void) {
node_t *head = malloc(sizeof(node_t));
head->val = 0;
strcpy(head->name, "");
head->next = NULL;
addFirst(15, "word", &head);
addFirst(14,"word2", &head);
printf("%i \n", findItem(15, "word", head));
}
The problem is in strcpy(head->name, "");. Here, you;re trying to use the memory location pointer to by head->name, but you never assigned a valid memory to it.
You need to make sure that the pointer points to a valid memory location, before you write to / read from that memory location. Attempt to access invalid memory invokes undefined behavior.
This is applicable for other uninitialized instances of name, too.
If you can live with POSIX standard, instead of strcpy(), you can make use of strdup()

Initialization of a structure that contains a pointer to an array

I have the following structure:
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE* node[26];
}TRIE_NODE;
I create a node called head, TRIE_NODE *head = NULL;, and then i try to initialize this node using the following function:
void initialize_node(TRIE_NODE *current_node)
{
int MAX = 25;
current_node = malloc(sizeof(TRIE_NODE));
for(int i = 0; i < MAX; i++)
{
current_node->node[i] = NULL;
if(current_node->node[i] == NULL)
printf("\n -- \n");
}
}
However, i get a segmentation fault whenever i try to even read current_node->node[i]. Does anyone have any idea of what's going on? Considering current_node->node is a pointer, that points to another pointer of type TRIE_NODE, shouldn't i be able to access it's values through bracket notation? (I've tried dereferencing it too, it doesn't compile)
You do everything correctly, except this line
current_node = malloc(sizeof(TRIE_NODE));
which modifies the local copy of current_node. The pointer in the caller remains unchanged.
To fix this problem, pass a pointer to pointer, and assign with an indirection operator:
void initialize_node(TRIE_NODE **current_node_ptr) {
...
*current_node_ptr = malloc(sizeof(TRIE_NODE));
...
}

Passing argument from incompatible pointer type warning

I've been trying to figure out pointers in C most of today, even asked a question earlier, but now I'm stuck on something else. I've got the following code:
typedef struct listnode *Node;
typedef struct listnode {
void *data;
Node next;
Node previous;
} Listnode;
typedef struct listhead *LIST;
typedef struct listhead {
int size;
Node first;
Node last;
Node current;
} Listhead;
#define MAXLISTS 50
static Listhead headpool[MAXLISTS];
static Listhead *headpoolp = headpool;
#define MAXNODES 1000
static Listnode nodepool[MAXNODES];
static Listnode *nodepoolp = nodepool;
LIST *ListCreate()
{
if(headpool + MAXLISTS - headpoolp >= 1)
{
headpoolp->size = 0;
headpoolp->first = NULL;
headpoolp->last = NULL;
headpoolp->current = NULL;
headpoolp++;
return &headpoolp-1; /* reference to old pointer */
}else
return NULL;
}
int ListCount(LIST list)
{
return list->size;
}
Now in a new file I have:
#include <stdio.h>
#include "the above file"
main()
{
/* Make a new LIST */
LIST *newlist;
newlist = ListCreate();
int i = ListCount(newlist);
printf("%d\n", i);
}
When I compile, I get the following warning (the printf statement prints what it should):
file.c:9: warning: passing argument 1 of ‘ListCount’ from incompatible pointer type
Should I be worried about this warning? The code seems to do what I want it to, but I'm obviously very confused about pointers in C. After browsing questions on this site, I found that if I make the argument to ListCount (void *) newlist, I don't get the warning, and I don't understand why, nor what (void *) really does...
Any help would be appreciated, thanks.
You're getting confused because of multiple typedefs. LIST is a type representing a pointer to struct listhead. So, you want your ListCreate function to return a LIST, not a LIST *:
LIST ListCreate(void)
The above says: ListCreate() function will return a pointer to a new list's head if it can.
Then you need to change the return statement in the function definition from return &headpoolp-1; to return headpoolp-1;. This is because you want to return the last available head pointer, and you have just incremented headpoolp. So now you want to subtract 1 from it and return that.
Finally, your main() needs to be update to reflect the above changes:
int main(void)
{
/* Make a new LIST */
LIST newlist; /* a pointer */
newlist = ListCreate();
int i = ListCount(newlist);
printf("%d\n", i);
return 0;
}

Resources