Link Lists and Freeing Memory in C - c

I was trying to make a simple Link List struct but for some reason when I tested freeing up the data in the LL it would give me an invalid pointer error. Can anyone explain why?
#include <stdio.h>
#include <stdlib.h>
void add();
typedef struct node{
char* data;
struct node* next;
} node;
node** n;
int main(int argv, char** argc){
n = (node**)malloc(sizeof(node*)*10);
int i;
for(i = 0; i < 10; i++){
n[i] = NULL;
}
add();
free(n[0]->data);
return 0;
}
void add(){
char* temp = (char*)malloc(sizeof(char)*4);
temp = "Meh\0";
n[0] = (node*)malloc(sizeof(node));
n[0]->data = temp;
}

char* temp = (char*)malloc(sizeof(char)*4);
temp = "Meh\0";
Your assignment to temp is the culprit, as that sets it to point to the static character string "Meh\0", which it not yours to free. Your malloc has no effect in this case, as you immediately replace it to point to static data instead. Use memcpy or similar if you want to copy the data into the memory allocated by malloc.

Related

Segmentation fault in assigning value to a dynamic array of Nodes, inside a structure

I am trying to create a Hash Map in C. Below is the code. When I try to
assign value to the elements of Darray ( each of which is a pointer to a Node) I am getting a segmentation fault ( i.e. at line 23 and24). Could anybody help in pointing out where am I going wrong.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
}Node;
typedef struct Map{
struct Node** Darray;
} Map;
#define SIZE 10
int main()
{
int i=0;
Map* M = malloc(sizeof(Map));
M->Darray = (struct Node**)malloc(sizeof(Node*)*SIZE);
for (i =0;i < SIZE;i++){
M->Darray[i]->data =0;
M->Darray[i]->next =NULL;
}
}
You allocate space for SIZE pointers to Node, but don't initialize these in any way, so when you access M->Darray[i] in M->Darray[i]->data you get segmentation fault because value of M->Darray[i] has not been set.
You need to allocate space for each node before using it:
for (i = 0; i < SIZE; i++) {
M->Darray[i] = malloc(sizeof(Node));
M->Darray[i]->data = 0;
M->Darray[i]->next = NULL;
}
Depending on your needs, you could also change Darray to be an array of nodes instead of node pointers, so you can allocate space for all nodes at once:
struct Node* Darray;
...
M->Darray = malloc(sizeof(Node) * SIZE);
for (i = 0; i < SIZE; i++) {
M->Darray[i].data = 0;
M->Darray[i].next = NULL;
}

how to make structs point to different strings?

I have a struct and in that a struct i have a character pointer but and i am creating different instances of this struct but when i am changing the pointer in one struct the other is also changing.
#include <stdio.h>
#include <stdlib.h>
typedef struct human{
int age;
char name[100];
} Human;
int main(){
FILE *s = fopen("h.txt","r");
if(s==NULL){
printf("file not available");
}
for(int i=0 ;i<5;i++){
Human h;
fscanf(s,"%d",&h.age);
fscanf(s,"%s",h.name);
insertintolinkedlist(h);
// this method is going to insert the human into the linked list
}
return 0;
}
what is happening that all humans in the linked list have different ages but same name!
You need to allocate memory to hold the name.
char* name is just a pointer - it has no memory for saving the name.
You change it to
char name[100];
Remember to check that the names you put into Human.name isn't longer than 100 characters.
To use a linked list you can do something like:
typedef struct human{
int age;
char name[100];
struct human* next;
} Human;
int main()
{
Human* head = NULL;
Human* tail = NULL;
for(.....)
{
Human* h = malloc(sizeof(Human));
if (head == NULL) head = h;
if (tail != NULL)
{
tail->next = h;
}
tail = h;
h->next = NULL;
h->age = ....;
strncpy(h->age, "..name..", 100);
}
// ..... other code
// Remember to free all allocated memory
}

Hash table in C always yields Seg fault

I am trying to develop a hash table in the C Programming Language which always fails with seg fault. I am trying to do seperate chaining so I created a struct which has two properties: word and next. The word is a char* and next a pointer to the next node, eventually creating a hash table that conatains an array of linked list.
typedef struct node
{
char* word;
struct node* next;
}node;
node* table[26];
After this I am indexing into the table by using a hashing function which simply indexes into the table.
Do you have a fix?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <cs50.h>
typedef struct node
{
char* word;
struct node* next;
}node;
node* table[26];
int hash(char* key);
void index();
int main(int argc, char* argv[])
{
index();
return 0;
}
int hash(char* key)
{
int hash = toupper(key[0]) - 'A';
int res = hash % 26;
return res;
}
void index()
{
printf("Insert a word: ");
char* k = GetString();
node* predptr = malloc(sizeof(node));
node* newptr = malloc(sizeof(node));
for(int i = 0; i < 26; i++)
{
if(hash(k) == i)
{
predptr = table[0];
predptr->next = newptr;
newptr = predptr;
break;
}
else
{
}
}
}
typedef struct node
{
char* word;
struct node* next;
}node;
node* table[26];
table is an array of 26 pointers, all initialized to NULL.
Specifically table[0] is a NULL pointer and you try to dereference it
predptr = table[0];
predptr->next = newptr; // dereference NULL pointer
// NULL->next
You created a table of 26 pointers to node structure, but did not allocate memory for them. Also, it is not clear what your GetString() method does and how the memory for the strings returned by it is managed. You have to use your (incomplete) index method (provided that you properly allocate necessary objects there) instead of just calling table[ha]->word = word; which segfaults because tabel[ha] does not point anywhere.
If you are doing hashing on word then change hashing function as
int hash(char *k){
int i=0;
for (;i<strlen(k) ;++i ){
//apply hashing technique
}
}
Your table has 26 NULL pointers , when you use
predptr = table[0];
predptr->next = newptr;
here predptr become NULL and then you are looking for it's next pointer which leads to segmentation fault .
To improve index performance you don't have to search for hashed index ,just goto that index < (No of maxm entries ) and follow it's pointer if it's null then add this word here it self else follow it's next pointer .

Linked Lists and binary data in C

I'm trying to write a simple C code for the following function:
Given an encoding for the letters a-d:
'a'->00, 'b'->01, 'c'->10, 'd'->11,
and a node in a linked-list defined as:
typedef struct listNode{
unsigned char data;
struct listNode* next;
}ListNode;
typedef struct list{
ListNode* head;
ListNode* tail;
}List;
where head points to the first node of the list, and the tail to the last one.
I need to write a function char* SumList(List arr[], int n), which returns a string which contains all the encoded letters in all the nodes of all lists in arr in row.
This is what I wrote so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isBitISet(char, int);
typedef struct listNode {
unsigned char data;
struct listNode* next;
} ListNode;
typedef struct list {
ListNode* head;
ListNode* tail;
} List;
int isBitISet(char ch, int i) {
char mask;
mask=1<<i;
return (mask & ch);
}
int totalNodes(List arr[], int n) {
int i;
int counter=0;
for (i=0; i<n; ++i) {
ListNode* head= arr[i].head;
while (head!=NULL) {
counter++;
head=head->next;
}
}
return counter;
}
char* whatToadd(char data) {
int a, b;
a=isBitISet(data, 0);
b=isBitISet(data, 1);
char* result;
result=(char *) calloc(2, sizeof(char));
if ((a!=0) && (b!=0))
result="d";
else if ((a!=0) && (b==0))
result="b";
else if ((a==0) && (b!=0))
result="c";
else
result="a";
return result;
}
char* SumLists(List arr[], int n) {
char* final;
int nodes=totalNodes(arr, n);
final= (char*) calloc(nodes, sizeof(char)); //how would I know the final length?//
int i;
for (i=0; i<n; ++i) {
ListNode* head= (arr[i].head);
while (head!=NULL) { //Why do I need a tail?//
char* result;
result=whatToadd(((head->data)&(00000011)));
strcat(final, result);
free(result);
result=whatToadd(((head->data)&(00001100))>>2);
strcat(final, result);
free(result);
result =whatToadd(((head->data)&(00110000))>>4);
strcat(final,result);
free(result);
result=whatToadd(((head->data)&(11000000))>>6);
strcat(final,result);
free(result);
head=head->next;
}
}
return final;
}
int main() {
.....
free(final);
...
}
Probably, Tail has given from some reason- but (1)- can't I run on the lists the way I did? without using the tail? and if not, how should I use it?
(2)- Do I need to free result the way I did each time I get a new result from whatToAdd?
I'm new to C, trying to work it by myself, I would really appricate tips and corrections. Thanks a lot.
Do I need to free result the way I did each time I get a new result from whatToAdd?
No, as the address of a string literal is being returned. Don't calloc() memory for result as it is unrequired. Change the return value of whatToadd() to const char*, as string literals are read-only.
Just to clarify, the following does not copy "d" into result:
result="d";
but instead makes result point to the address of the string literal "a": it is a pointer assignment. If you wanted to copy into result you could do either:
strcpy(result, "d");
*result = 'd'; *(result + 1) = 0;
in which case you would free() the returned pointer.
Only pass a pointer to free() if it is the result of a previous call to calloc(), malloc() or realloc() and has not already been free()d.

C dynamic array problem

I wrote a piece of code to handle dynamic arrays. Idea was to use array of struct pointers, where the last member of array is NULL. Slight variation of code I wrote is below (using integers and not structures).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int **list, int* value) {
for(int i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
}
void list_init(int **list) {
int* x;
for(int i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(list, x);
}
}
int main() {
int** l = malloc(sizeof(int*));
l[0] = NULL;
list_init(l);
}
While debugging, I discovered that only first 3 integers are added to the list. I can't seem to figure out why is this happening. Any ideas?
The problem is that the call to realloc() in list_add() potentially frees the memory block *list and allocates another. list_add updates its list pointer, but it does not return the updated pointer to the caller, list_init(); list_init()'s list pointer is potentially a pointer to the recently-freed memory block.
To fix this code, list_add() and list_init() need to be able to "return" the updated list pointer:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int ***p_list, int *value) {
int **list = *p_list;
int i;
for(i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
*p_list = list;
}
void list_init(int ***p_list) {
int **list = *p_list;
int *x;
int i;
for(i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(&list, x);
}
*p_list = list;
}
int main() {
int **list = malloc(sizeof(int*));
list[0] = NULL;
list_init(&list);
int **l = list;
for (; *l != NULL; ++l) {
printf("%d\n", **l);
}
}
http://codepad.org/iGcSaJOR
EDIT
In this case of dynamic arrays the way you have told will not make anything better, the code will complicate only. For each addition of integer you have used realloc trying aggressively to save memory, but this will take more time while execution. Why not allocate a block of memory reserved for the array and to reflect the dynamic character put the array inside a struct with the last index, and when you add something add it on the last location and increment the counter. When this block is filled, you can chain another block to point to another one.
typedef struct _dyna_arr
{
my_type data_arr[MAX_LEN];
int n;
struct _dyna_arr *next block;
};
Therefore you maintain a linked list of multiple arrays. The size of MAX_LEN can be fixed which is appropriate for an application which will help decrease internal fragmentation.
*old answer removed *

Resources