Pointer with double pointer - c

Why cant I assign a pointer to a double pointer's pointer? I get segmentation fault every time.
#include <stdio.h>
int main() {
int **pointer1, *pointer2, *pointer3, var;
var = 10;
pointer3 = &var;
pointer1 = &pointer3;
pointer2 = *pointer1; //correcting my mistake, so this is now correct?
return 0;
}
The code I was actually working on, practicing linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t **head, *temp;
*head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, head);
}
temp = *head;
/*while (temp != NULL) { //here is the problem, if I remove this
//I get segmentation fault but it runs
printf("%d ", temp->num); //runs fine when I include it
temp = temp->next;
}*/
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Just like what I put in the code comment, the above version of my code gets segmentation fault when I compile it without the while loop. But weirdly enough, it works fine once I include the while loop. After fiddling around, I suspect the culprit to be the double pointer in which I tried to assign the secondary address into a regular pointer.
But this version actually runs fine:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t *head, *temp;
head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, &head);
}
temp = head;
while (temp != NULL) {
printf("%d ", temp->num);
temp = temp->next;
}
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Over here I passed the address into the linked list function and essentially I'm doing the same thing but without the double pointer.
On a side note, I have seen many different implementations of linked lists. Mine requires the double pointer because I'm using a void insert(int, **node_t), but there are versions which returns the address and updates the head: node_t* insert(int, *node_t) and Global linked list: void insert(int). Just wondering which versions are actually recommended, easier to debug and beginner friendly.

Your first example segfaults because *pointer1 (and pointer1 before it) isn't pointing to anything. It's an uninitialized pointer that points to random garbage data in memory.
Trying to dereference such a pointer (**pointer1 = 10;) results in a segfault.
A solution to make your first example work would be to allocate some memory for the data you're trying to store :
int **pointer1, *pointer2;
int *data = malloc(sizeof(int));
pointer1 = &data;
**pointer1 = 10;
pointer2 = *pointer1;
free(*pointer1); //or free(data)

When you do this:
**pointer1 = 10;
What this says is "take the address stored in pointer1, dereference that address, take the address stored there, dereference again, and store the value 10 at that location".
It looks something like this:
pointer1
------- ------- ------
| .--|---->| .--|--->| 10 |
------- ------- ------
You're getting a segfault because pointer1 doesn't currently point anywhere.
This could work if you do something like this:
int **pointer1, *pointer2, value;
value = 10;
pointer2 = &value;
pointer1 = &pointer2;
In the case of the two "real" code snippets, the problem with the first piece of code is that you pass head uninitialized to insert, which then subsequently dereferences head. This is the same problem as above. The same thing happens again in main because head is still uninitialized after calling list because it was passed by value. The second piece of code works because you pass the address of head to insert, so subsequently dereferenced it is valid.

Related

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()

referenced values are lost with stack frame collapse

I am currently attempting to load values from an array into a stack data structure that I have implemented with a linked list. In my push() function I create each new node in my linked list through the use of a pointer so that they do not disappear when the push() stack frame collapses and control returns to reverse(). However, even though I am passing information through the use of pointers, the item I am referencing appears not be returning, as I keep getting NULL values in the calling function despite getting valid values in the called function. Why is this information not returning to my calling function?
#include<stdio.h>
#include<stdlib.h>
struct Node
{
char data;
struct Node* next;
};
void push(char x, struct Node* tp)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node*));
temp->data = x;
temp->next = tp;
tp=temp;
printf("\ntp points to %p", tp);
}
void reverse (char c[])
{
struct Node* tp = NULL;
int i = 0, j = 0;
while (c[i] != '\0')
{
push(c[i], tp);
printf("\ntp points to %p", tp);
i++;
}
}
int main(void)
{
char c[] = {"coolio"};
printf("\n%s", c);
reverse(c);
}
The problem is that push cannot change tp that you pass it from reverse, because tp is passed by value. Change the function to return the value to be assigned to tp, like this:
struct Node* push(char x, struct Node* tp) {
... // your code here
return temp;
}
The call should look like this:
while (c[i] != '\0') {
tp = push(c[i], tp);
printf("\ntp points to %p", (void*)tp);
i++;
}
Note that using %p requires a cast to void*.
Demo.

How to make changes in an array through a function

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node{
int value;
NODE* next;
};
int hash(int);
void insert(int,NODE **);
int main(){
NODE* hashtable[SIZE];
insert(12,&hashtable[SIZE]);
printf("%d\n",hashtable[5]->value);
}
int hash(int data){
return data%7;
}
void insert(int value,NODE **table){
int loc = hash(value);
NODE* temp = malloc(sizeof(NODE));
temp->next = NULL;
temp->value = value;
*table[loc] = *temp;
printf("%d\n",table[loc]->value);
}
The above code prints :
12 and
27475674 (A random number probably the location.)
how do I get it to print 12 and 12 i.e. how to make a change in the array. I want to fill array[5] with the location of a node created to store a value.
The expression *table[loc] is equal to *(table[loc]) which might not be what you want, since then you will dereference an uninitialized pointer.
Then the assignment copies the contents of *temp into some seemingly random memory.
You then discard the memory you just allocated leading to a memory leak.
There's also no attempt to make a linked list of the hash-bucket.
Try instead to initially create the hashtable array in the main function with initialization to make all pointers to NULL:
NODE* hashtable[SIZE] = { NULL }; // Will initialize all elements to NULL
Then when inserting the node, actually link it into the bucket-list:
temp->next = table[loc];
table[loc] = temp;
This is just a simple change which I have made to your program which will tell you what you are actually doing wrong.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node {
int value;
NODE* next;
};
NODE *hashtable[SIZE] = { NULL };
int hash(int);
int insert(int); //, NODE **);
int main(void)
{
int loc = insert(12); //, &hashtable[SIZE]);
if (loc < SIZE) {
if (hashtable[loc]) {
printf("%d\n", hashtable[loc]->value);
} else {
printf("err: invalid pointer received\n");
}
}
return 0;
}
int hash(int data)
{
return data%7;
}
int insert(int value) //, NODE *table[])
{
int loc = hash(value);
printf("loc = %d\n", loc);
if (loc < SIZE) {
NODE *temp = (NODE *) malloc(sizeof(NODE));
temp->value = value;
temp->next = NULL;
hashtable[loc] = temp;
printf("%d\n", hashtable[loc]->value);
}
return loc;
}
Here I have declared the hashtable globally just to make sure that, the value which you are trying to update is visible to both the functions. And that's the problem in your code. Whatever new address you are allocating for temp is having address 'x', however you are trying to access invalid address from your main function. I just wanted to give you hint. Hope this helps you. Enjoy!

Trouble with insertion of C string into linked list

I am writing a program to read a file and then store the data into a linked List.
linkedList.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
struct linked_list
{
char *stock_name;
double stock_price;
struct linked_list *next;
};
typedef struct linked_list NODE;
NODE* insert(NODE *head, double stock_price, char *stock_name);
void printList(NODE *head);
linkedList.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include"linkedList.h"
void printList(NODE *head)
{
NODE *this = head;
while(this != NULL)
{
printf("stock name:%s , stock price:%lf\n", this->stock_name, this->stock_price);
this = this->next;
}
}
NODE* insert(NODE *head, double stock_price, char *stock_name)
{
NODE *newNode = malloc(sizeof(NODE));
if(head == NULL)
{
newNode->stock_price = stock_price;
newNode->stock_name = stock_name;
head = newNode;
}
else
{
newNode->stock_price = stock_price;
newNode->stock_name = stock_name;
newNode->next = head;
head = newNode;
}
return head;
}
main.c
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "linkedList.h"
NODE *head;
bool headNode = true;
void insertIntoLinkedList(char *stock_name, double stock_price);
int main ( int argc, char *argv[] )
{
head = malloc(sizeof(NODE));
double stock_price;
char stock_name[100];
int stock_name_counter = 0;
**..then I read the file..**
stock_name[stock_name_counter] = '\0'; //to end my C string
stock_name_counter = 0; //this is used for reading char
insertIntoLinkedList(stock_name, stock_price); //I double checked here,the name and price is correct
**......**
printList(head); //**Not the output I want**
fclose( file );
void insertIntoLinkedList(char *m_stock_name, double m_stock_price)
{
if(headNode == true)
{
head = insert(NULL, m_stock_price, m_stock_name);
headNode = false; //this is used to insert data to my linked list for the first time
}
else
{
head = insert(head, m_stock_price, m_stock_name);
}
}
Here is the problem: if the file contains:
YAHOO 120
GOOGLE 10
APPLE 199
my printList() gave me this:
APPLE 120
APPLE 10
APPLE 199
I have been trying to debug for hours and still cannot figure why the name is not stored in my linked list properly(but the price is store properly..)...any help will be appreciate :)
The address of stock_name in main is always constant through out the program and you store that address to newNode->stock_name and so you will always get the last stored string in stock_name.
Modification
NODE* insert(NODE *head, double stock_price, char *stock_name)
{
NODE *newNode = malloc(sizeof(NODE));
newNode->stock_name = malloc(strlen(stock_name)+1);
if(head == NULL)
{
newNode->stock_price = stock_price;
strcpy(newNode->stock_name, stock_name);
head = newNode;
}
else
{
newNode->stock_price = stock_price;
strcpy(newNode->stock_name, stock_name);
newNode->next = head;
head = newNode;
}
return head;
}
Don't forget to free the allocated memory.
You need to make a copy of the string stored in stock_name when you call insert. As is, all the nodes point to the same buffer, and every time you read a new line, you overwrite the buffer. In the end, this means that all of the nodes have the text APPLE because that's the last content that's read into the shared buffer. If you either copy the buffer's contents (instead of just the pointer to the buffer) or allocate a new buffer every time you read from the file, this will be fixed.
Your basic problem is that C does not have a "String" type. A string is simple an array of characters, and an array "decays" to a pointer when used as an argument to a function. Based on the way you're using it, your insert() function should do a second malloc() to allocate storage for the string and use strdup() or similar to store it.
Your other problem is that you've got a logic flaw in the insert() function. You aren't initializing newNode->next if head is NULL. You should be doing newNode->next = head either way. If it's NULL, good. Your list tail will then not be pointing at an indeterminate place.

Simple Linked List C code Segmentation fault

I am making a linked list program for my basic C assignment.
However, I will always get the force closed error on .exe and get a segmentation fault on Ubuntu.
I tried to break it down and rewrite but I have no idea where the code fails.
I'd appreciate your help.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node{
char name[20];
int mark;
struct node *next;
};
struct node *addnode(char name[], float mark);
int main(void){
int j = 0;
char StdName[10];
float StdMarks;
struct node *head = NULL;
struct node *curr = NULL;
head = curr = addnode('\0',0.0);
for(j=0; j<3; j++){
printf("\nEnter StdName >>");
printf("\nMarks for %s >>", StdName);
curr -> next = addnode("", 5.5);
curr = curr->next;
}
curr = head -> next;
j = 0;
printf("\nnode\tName\tMarks");
while(curr){
printf("\n%d\t%s\t%5.2f", j++, curr->name, curr->mark);
curr=curr->next;
}
return 0;
}
struct node *addnode(char name[], float mark){
struct node *temp;
temp=(struct node*)malloc(sizeof(struct node));
strcpy(temp->name,name);
temp->mark=mark;
temp->next=NULL;
return (temp);
}
A few mistakes:
'\0' is not a char[], but a char whose value is 0 and converted to a char* (NULL pointer). Use "" for an empty string. The compiler should have emitted a warning for this. Compile with warning level at highest and treat warnings as errors (so you cannot ignore them). For gcc the flags are -Wall -Werror.
StdName is not initialised and is never populated but is used in a printf("%s") call.
The first node you add you use a single char '\0' for name, when you should pass a string:
head = curr = addnode("", 0.0);
And also this doesn't point to the first node, it points to the second one:
curr = head -> next;
Should be:
curr = head;
I don't know what you intended to do with StdName but as hmjd said, it should be initialized to some value.
char StdName[] ="stdname";
head = curr = addnode('\0',0.0); line is invalid. Your addnode function expects a pointer to characters array as first parameter. '\0' is an integer value equal to 0. You pass the name to strcpy which uses it as a pointer to source data. Since the pointer is 0 (== NULL), you get a crash.

Resources