Why is "free" saying this that my pointer is invalid? - c

while(n >= 0);
node * point = malloc(sizeof(node));
point = create(number, n);
//show(point);
//free memory
while(point != NULL)
{
node *tmp = point->next;
free(point);
point = tmp;
}
}
node * create(int data[], int len)
{
node * list_head;
node * list;
for (int i = 0; i < len; i++)
{
if(i == 0)
{
list_head = malloc(sizeof(node));
list = malloc(sizeof(node));
list_head->value = data[0];
list_head->next = list;
}
else
{
list->value = data[i];
list->next = malloc(sizeof(node));
list->next = NULL;
}
}
return list_head;
}
This code is returning an error which is:- free(): invalid pointer
Aborted | Why is my code not freeing the memory that I allocated. Is it because I have allocated that in some different function?

The code you posted should be changed to:
while(n >= 0) {
node * point = create(number, n);
and:
list->next = NULL;
should be changed to
list = list->next;

Related

variable "tmp" used in loop condition not modified in loop body

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node* next;
}
node;
int main(void){
node* list = NULL;
node *n = malloc(sizeof(node));
if(n==NULL){
return 1;
}
n->number = 2;
n-> next = NULL;
list = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list);
return 1;
}
n->number = 3;
n->next = NULL;
list->next = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list->next);
free(list);
}
n->number = 4;
n->next = NULL;
list->next->next =n;
n = malloc(sizeof(node));
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
for( node* tmp = list; tmp != NULL; tmp->next){
printf("%i\n" , tmp->number);
}
while(list!=NULL){
node*tmp = list->next;
free(list);
list=tmp;
}
}
was trying linked list.
expected when running the code:
0
1
2
3
4
$
//asdoihasidashiofdhiohdfgdiwheifiopioioiophfaifjasklfhafiashfauiosfhwuiohwefuiowhfaslfidasdaskdasjdlaksdjqwfiqpweiojfkldfjsdfklwhefiowefweopfiosfkosid;fjwdfp;fdasiopfjew[0fowejfwepfojmofejmiwrfgj;wdfjewio;fijwefjsdp;jfkl;wjw
Actually you are not changing the pointer
for( node* tmp = list; tmp != NULL; tmp->next){
You need to write
for( node* tmp = list; tmp != NULL; tmp = tmp->next){
It will be even better to write
for ( const node* tmp = list; tmp != NULL; tmp = tmp->next ){
because within the loop the list is not being changed.
Also in this code snippet
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
the statement
n->next = NULL;
is redundant.
In this loop, tmp->next has no effect because you don't assign it to anything.
for (node* tmp = list; tmp != NULL; tmp->next) {
printf("%i\n", tmp->number);
}
You must do tmp = tmp->next:
for (node* tmp = list; tmp != NULL; tmp = tmp->next) {
// ^^^^^
printf("%i\n", tmp->number);
}
Also, you can't expect 1 to be in the output because you never create a node with that number. With the above change the program will therefore output:
0
2
3
4
Sidenote: Your program is full of repetition which makes it hard to find errors and it's also what makes it harder to see that you forgot to add the node with the number 1. If you instead make functions of the things that you do repeatedly it'll be much clearer. You can also make functions with descriptive names to make the whole program easier to read and maintain.
If your program was rewritten to make use of functions, it could look like below - and then it'll be very obvious that the node with the number 1 is missing.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
int number;
node* next;
};
node *create_node(int number, node *next) {
node *nn = malloc(sizeof *nn);
if(!nn) exit(1);
// assign values to the new node:
*nn = (node){.number = number,
.next = next};
return nn;
}
void insert_first(node **list, int number) {
*list = create_node(number, *list);
}
void insert_last(node **list, int number) {
// find the last "next" pointer (the one pointing at NULL):
while(*list) list = &(*list)->next;
// make the pointer pointing at NULL now point at the new node:
*list = create_node(number, NULL);
}
void free_all(node **list) {
for(node *tmp; *list; *list = tmp) {
tmp = (*list)->next;
free(*list);
}
}
void print_all(const node *list) {
for (; list; list = list->next) {
printf("%d\n", list->number);
}
}
int main(void) {
node* list = NULL;
insert_last(&list, 2);
insert_last(&list, 3);
insert_last(&list, 4);
insert_first(&list, 0);
print_all(list);
free_all(&list); // list == NULL after this
}

Implementing mergesort on a linked list

I was tasked with implementing a merge sort algorithm on a list written in C/C++. I have the general idea down, wrote my code and have successfully compiled it. However, when I run it, it will begin fine but then hang on "prepared list, now starting sort" without giving any kind of error. I have tried to look through my code but I am at a complete loss as to what the issue could be. I am also pretty amateurish with debugging, so using gdb to the best of my abilities has lead me no where. Any advice or tips would be a tremendous help, thank you all!
#include <stdio.h>
#include <stdlib.h>
struct listnode
{
struct listnode *next;
int key;
};
//Finds length of listnode
int
findLength (struct listnode *a)
{
struct listnode *temp = a;
int i = 0;
while (temp != NULL)
{
i++;
temp = temp->next;
}
return i;
}
struct listnode *
sort (struct listnode *a)
{
// Scenario when listnode is NULL
if (findLength (a) <= 1)
return a;
//Find middle
int mid = findLength (a) / 2;
struct listnode *temp = a;
struct listnode *first = a;
struct listnode *second;
for (int i = 0; i < mid - 1; i++)
{
temp = a->next;
}
second = temp->next;
temp->next = NULL;
//Recursive calls to sort lists
first = sort (first);
second = sort (second);
if (first != NULL && second != NULL)
{
if (first->key < second->key)
{
a = first;
first = first->next;
}
else
{
a = second;
second = second->next;
}
}
struct listnode *head = a;
struct listnode *tail = a;
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail = first;
first = first->next;
tail = tail->next;
}
else
{
tail = second;
second = second->next;
tail = tail->next;
}
}
if (first == NULL)
{
while (second != NULL)
{
tail = second;
second = second->next;
tail = tail->next;
}
}
while (first != NULL)
{
tail = first;
first = first->next;
tail = tail->next;
}
return a;
}
Here is the test code provided, written in C:int
main (void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc (500000 * sizeof (struct listnode));
for (i = 0; i < 500000; i++)
{
(space + i)->key = 2 * ((17 * i) % 500000);
(space + i)->next = space + (i + 1);
}
(space + 499999)->next = NULL;
node = space;
printf ("\n prepared list, now starting sort\n");
node = sort (node);
printf ("\n checking sorted list\n");
for (i = 0; i < 500000; i++)
{
if (node == NULL)
{
printf ("List ended early\n");
exit (0);
}
if (node->key != 2 * i)
{
printf ("Node contains wrong value\n");
exit (0);
}
node = node->next;
}
printf ("Sort successful\n");
exit (0);
}
You're close, but with some silly errors. Check the append operations in the merge step. They're not doing what you think they are. And of course you meant temp = temp->next; in the splitting loop.
If gdb is overwhelming, adding printf's is a perfectly fine way to go about debugging code like this. Actually you want to write a list printing function and print the sublists at each level of recursion plus the results of the merge step. It's fun to watch. Just be neat and delete all that when you're done.
Here's code that works for reference:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
while (fst && snd) {
if (fst->key < snd->key) {
tail->next = fst;
tail = fst;
fst = fst->next;
} else {
tail->next = snd;
tail = snd;
snd = snd->next;
}
}
while (fst) {
tail->next = fst;
tail = fst;
fst = fst->next;
}
while (snd) {
tail->next = snd;
tail = snd;
snd = snd->next;
}
tail->next = NULL;
return rtn->next;
}
On my old MacBook this sorts 10 million random integers in a bit over 4 seconds, which doesn't seem too bad.
You can also put the append operation in a macro and make this quite concise:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
#define APPEND(X) do { tail->next = X; tail = X; X = X->next; } while (0)
while (fst && snd) if (fst->key < snd->key) APPEND(fst); else APPEND(snd);
while (fst) APPEND(fst);
while (snd) APPEND(snd);
tail->next = NULL;
return rtn->next;
}
Does it have to be a top down merge sort? To get you started, here's a partial fix, didn't check for other stuff. The | if (first != NULL && second != NULL) | check isn't needed since the prior check for length <= 1 takes care of this, but it won't cause a problem.
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail->next = first;
tail = first;
first = first->next;
}
else
{
tail->next = second;
tail = second;
second = second->next;
}
}
if (first == NULL)
{
tail->next = second;
}
else
{
tail->next = first;
}
}

Linked list only prints the first value of first list

I have a program where three values are inserted into linked lists. When I try to iterate through the list I only get the first value printed. Sorry if the function names are confusing I'm still new to c and I'm trying to use the function and variable names gave me just to make my life easier when taking a test. I'm also pretty unfamiliar with debugger and how I would use it to find out what is going on here. Thanks in advance.
void program_header(char i[]);
Node *allocateNode(int iNewInfo);
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes);
Node *insertLL(Node **ppHead, int iNewInfo);
void printLL(Node *pHead);
int main(int argc, char *argv[])
{
program_header(argv[0]);
insertLL(&pHead, 84);
insertLL(&pHead, 45);
insertLL(&pHead, 81);
printLL(pHead);
return 0;
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct Node
{
int iInfo;
struct Node *pNext;
}Node;
Node *pHead = NULL;
Node *pNew = NULL;
Node *pPrecedes = NULL;
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
printf("Memory allocation error");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
printf("Found! %d\n", iMatch);
return p;
if (iMatch < p->iInfo)
return NULL;
*ppPrecedes = p;
}
return NULL;
}
Node *insertLL(Node **ppHead, int iNewInfo)
{
Node *pFind;
// see if it already exists
pFind = searchLL(*ppHead, iNewInfo, &pPrecedes);
if(pFind != NULL)
return pFind;
// Doesn't already exist. Allocate a node and insert it
pNew = allocateNode(iNewInfo);
if(pPrecedes == NULL)
{ //insert at head
pNew->pNext = *ppHead;
*ppHead = pNew;
}
else
{ //insert after a node
pNew->pNext = pPrecedes->pNext;
pPrecedes->pNext = pNew;
}
return pNew;
}
void printLL(Node *pHead)
{
Node *p;
printf("iInfo Values\n");
for (p = pHead; p != NULL; p = p->pNext)
{
printf("%d\n", p->iInfo);
}
p = pHead;
}
void program_header(char i[])
{
int j, n = strlen(&i[2]);
char *name = &i[2], border[n], dash = '-';
// loads dashes into array
for(j = 0; j < n; j++)
border[j] = dash;
border[j] = '\0';
// print header
printf("\n~%s~\n~%s~\n~%s~\n\n"
, border, name, border);
}
I believe your problem is in your search method. I have reformatted it to show the way that it is currently behaving. To help in making your code more readable and to avoid these type of errors you should get in the habit of using braces in your if statements even if they are only one line.
This is your current code
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
{
printf("Found! %d\n", iMatch);
}
return p;
if (iMatch < p->iInfo)
{
return NULL;
}
*ppPrecedes = p;
}
return NULL;
}
Notice in the for loop that no matter if a match is found or not you are always returning p which is really pHead. Then in your insert code you are checking to see if the item is found in the list. Since you always return head it thinks that the item is in the list and never adds a new item.
I haven't tested this, but I believe this is the change you would need to make. You are expecting the search to return a node if the value is already in the list. So you want to return p if there is a match, otherwise you want to return NULL:
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
{
printf("Found! %d\n", iMatch);
return p;
}
if (iMatch < p->iInfo)
{
return NULL;
}
*ppPrecedes = p;
}
return NULL;
}
correct this
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
printf("Memory allocation error");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
to this
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew){
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
}else{
printf("Memory allocation error");
}
return pNew;
}

How to combine in one loop serial numbers and null?

I'm busy with implementation of singly linked list and have 2 functions: insert_back and insert_after.
Here is the listing of them:
void insert_back(int data)
{
node *temp1;
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
while (temp1->next != NULL) {
temp1 = temp1->next;
}
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data = data;
temp->next = NULL;
temp1->next = temp;
}
void insert_after(int pos, int data)
{
node *temp1;
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
for (int i = 1; i < pos; i++) {
temp1 = temp1->next;
if (temp1 == NULL) {
return;
}
}
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data = data;
temp->next = temp1->next;
temp1->next = temp;
}
As you can see they are almost the same and for insert back I want to write insert_after(null, 10). I can solve it by adding if condition and choose one of the loops, but it's not my aim.
Is it possible somehow to use one while or for loops together for serial numbers and null?
Also I see that param int pos is int. Should I use 0 instead of null?
You unnecessarily allocate memory in the following lines.
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
This allocated memory will leak as you overwrite the returned address in temp1. You just need temp1 to walk over the list, so there is also no need to allocate any node itself. temp1 can point to any node.
I've taken the liberty to kind of from scratch write a routine doing both things in one go. If pos < 0 it will add the element to the end of the list, otherwise it will add it after the pos-th element, where the first element corresponds with pos == 1. If pos == 0 the element is added at the start of the list.
Also a small main is added to test the routine. new_node has been added to test if memory is not exhausted.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
struct node * next;
int data;
} node;
node * head = NULL;
node * new_node(void)
{
node * result = malloc(sizeof(*result));
if (result == NULL)
{
fprintf(stderr, "Out of memory.\n");
exit(10);
}
return result;
}
void insert_after(int pos, int data)
{
node *walk, * prev;
int i;
prev = NULL;
walk = head;
for (i = 0; walk != NULL && i != pos; i++)
{
prev = walk;
walk = walk->next;
}
if (i != pos && pos > 0)
{
fprintf(stderr, "Location not found.\n");
exit(9);
}
else
{
walk = new_node();
walk->data = data;
if (prev == NULL)
{
walk->next = head;
head = walk;
}
else
{
walk->next = prev->next;
prev->next = walk;
}
}
}
int main(void)
{
int i;
node * wlk;
for (i = 0; i < 10; i++)
{
insert_after(-1, i);
}
for (i = 0; i < 10; i++)
{
insert_after(3, i+10);
}
for (wlk = head; wlk != NULL; wlk = wlk->next)
{
printf("%d\n", wlk->data);
}
return 0;
}
Since you are testing for the end of the chain with insert_after(pos,...) anyway, you could go for:
void insert_after(int pos, int data)
{
node *temp1= head;
for (int i=1; i<pos; i++) {
if (temp1->next==NULL) {
if (pos==INT_MAX)
break; // pos of INT_MAX means insert at end
// so we continue with this last item and append
else
return; // pos higher than length of chain
}
temp1 = temp1->next;
}
...
}
Or slightly more compact:
void insert_after(int pos, int data)
{
node *temp1= head;
for (int i=1; i<pos && temp1->next!=NULL; i++) {
temp1 = temp1->next;
}
if (temp1->next==NULL && pos!=INT_MAX)
return; // pos higher than length of chain, except for
// INT_MAX (for that we just want to continue)
...
}
Then you could use
void insert_back(int data)
{
insert_after(INT_MAX, data);
}

why is this print linked list function not working?

I have a function as following
void printLinkedList(struct node *head) {
printf("%d-->", head->data);
while(head->ptr != NULL) {
head = head->ptr;
printf("%d-->", head->data);
}
printf("NULL\n");
}
I would like to print the content of a linked list constructed in the following way:
for (int i = 0; i < 10; i++) {
head->data = i+1;
head->ptr = malloc(sizeof(struct node));
head = head->ptr;
}
So ideally this should give me something like:
1-->2-->3-->4-->...-->10-->NULL
If everything is correct, however, valgrind is giving me memory errors. Please tell me what I am doing wrong.
check this.
struct node *temp, *head= NULL, *last = NULL;
for (int i = 0; i < 10; i++) {
temp = malloc(sizeof(struct node));
temp->data = i+1;
temp->ptr = NULL;
if (head == NULL)
head = temp;
if (last != NULL)
last->ptr = temp;
last = temp;
}
printLinkedList(head);
I revised Toms's answer a little:
struct node *head = NULL, **temp = &head;
for (int i = 0; i < 10; i++) {
*temp = malloc(sizeof(struct node));
(*temp)->data = i+1;
(*temp)->ptr = NULL;
temp = &(*temp)->ptr;
}
printLinkedList(head);
The orignal code produces a seg fault because temp is not malloced properly.
If you call print function without constructing the Linked list, it will show error, so change the print function as follows:
void printLinkedList(struct node *head)
{
while(head != NULL)
{
printf("%d-->", head->data);
head = head->ptr;
}
printf("NULL\n");
}
here is the revised code - your construction was faulty.
typedef struct _node {
int data;
struct _node *ptr;
} NODE, *PNODE;
PNODE head;
int main (int argc, char * argv[])
{
head = (PNODE) malloc(sizeof(NODE));
PNODE node = head;
int i = 0;
node->data = ++i;
node->ptr = NULL;
for ( ;i < 10; ) {
PNODE tmp = (PNODE) malloc(sizeof(NODE));
tmp->data = ++i;
tmp->ptr = NULL;
node->ptr = tmp;
node =tmp;
}
printLinkedList(head);
freeLinkedList(head);
return 0;
}

Resources