I don't understand why when I run this code, the printf statements aren't working.
Here is the code:
typedef struct list {
int n;
struct list *next;
}List;
List **head;
List *tmp=malloc(sizeof(List));
tmp->n=34;
tmp->next=NULL;
List *tmp2=malloc(sizeof(List));
tmp2->n=45;
tmp2->next=NULL;
List *tmp3=malloc(sizeof(List));
tmp3->n=26;
tmp3->next=NULL;
head=malloc(sizeof(head));
head[0]=tmp;
head[1]=tmp2;
head=realloc(head,sizeof(head));
head[2]=tmp3;
printf("n of tmp:%d \n",head[0][0].n);
printf("n of tmp2:%d \n",head[1][0].n);
printf("n of tmp3:%d \n",head[2][0].n);
I think that the reason for that is probably realloc, but why ? I'm using it properly, no ? I have followed this tutorial http://www.tutorialspoint.com/c_standard_library/c_function_realloc.htm
Not only realloc, here
head = malloc(sizeof(head));
You allocate space for just one pointer, and then
head[0]=tmp;
head[1]=tmp2;
you try to store 2.
If you need space for 2 pointers, then the correct way is
head = malloc(2 * sizeof(*head));
/* ^ always dereference when using sizeof */
/* in this case it's not a problem, but in other cases it will be */
then you can fill the two elements, after checking the return value of malloc() so
head = malloc(2 * sizeof(*head));
if (head == NULL)
doSomething_But_DontDereference_head_mayBe_exit();
head[0] = tmp;
head[0] = tmp2;
Now, realloc(), what if realloc() returns NULL, and you alread overwrite the head pointer, now you can't do anything else with it, so
void *pointer;
pointer = realloc(head, 3 * sizeof(*head));
if (pointer == NULL)
doSomethingAndProbablyFree_head_and_abort();
head = pointer;
is much safer.
And also, note that you need to multiply the size of the pointer sizeof(*head) by the number of pointers you want to store.
ALWAYS CHECK THE RESULT OF malloc()
Your code is relatively broken. Here's a fairly sane way of going about this:
typedef struct list {
int n;
struct list *next;
} List;
int main() {
List *tmp1 = malloc(sizeof(List));
tmp1->n = 34;
tmp1->next = NULL;
List *tmp2 = malloc(sizeof(List));
tmp2->n = 45;
tmp2->next = NULL;
List *tmp3 = malloc(sizeof(List));
tmp3->n = 26;
tmp3->next = NULL;
List **head = malloc(2 * sizeof(List *));
head[0] = tmp1;
head[1] = tmp2;
head = realloc(head, 3 * sizeof(List *));
head[2] = tmp3;
printf("n of tmp1: %d\n", head[0]->n);
printf("n of tmp2: %d\n", head[1]->n);
printf("n of tmp3: %d\n", head[2]->n);
}
I haven't included this, but you should also verify that malloc() and realloc() return a non-null pointer.
Related
so, I just coded a Insertion Sort to sort a linked list (wiith dummy cell).
It works pretty good, but, at the end of the code, If I use free() in a pointer that I used as auxiliar, It's free also one of my cell (the last one it pointer in the loop).
So in order to avoid it free my cell, first I'm pointing de pointer to NULL, but here's my question: Wasn't it supposed to free just the pointer and not my cell if I didn't pointed NULL?
Here's my function
void
insertSort(cel *lst){
cel *temp = NULL;
cel *ordenado = lst->prox;
while(ordenado){
cel *valorOrdenando = ordenado->prox;
// removendo o valorOrdenado da lista
ordenado->prox = valorOrdenando->prox;
for (cel* i = lst; i != ordenado->prox; i = i->prox)
{
if (valorOrdenando->valor <= (i->prox)->valor || i->prox == ordenado->prox){
temp = i->prox;
i->prox = valorOrdenando;
valorOrdenando->prox = temp;
break;
}
}
ordenado = ordenado->prox;
}
// and here is where I point to NULL, otherwise I lost a cell
temp = NULL;
free(temp);
}
Here's the other part of the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct cel {
int valor;
struct cel *prox;
}typedef cel;
void inserir (cel **lista, int x) {
cel *temp = NULL, *aux = *lista;
temp = malloc(sizeof(cel));
temp->valor = x;
temp->prox = NULL;
if (*lista == NULL)
*lista = temp;
else {
for (; aux->prox != NULL; aux = aux->prox);
aux->prox = temp;
}
}
void imprimir(cel *lista) {
for (cel *aux = lista; aux != NULL; aux = aux->prox)
printf("%d ,", aux->valor);
printf("\n");
}
int main(){
cel *list = NULL;
inserir(&list, 3);
inserir(&list, 2);
inserir(&list, 1);
inserir(&list, 8);
inserir(&list, 6);
insertSort(list);
//bubbleSort(list->prox);
imprimir(list->prox);
return 0;
}
How should I code so that I didn't need to user *temp = NULL and why Is it happening currently??
You have a misconception about how pointers work in C. When you declare a pointer, it is just like declaring any other variable.
If you declare a pointer locally (inside a function, without a modifier such as static) the memory position it occupies will be handled by lower layers that the language C abstracts for you. One common implementation is to use a stack, when you declare a variable locally it will be pushed onto the stack when the function is called and will be popped out of the stack once the function returns, so there is no need to worry about deallocating your pointers.
However, a pointer points to a certain memory position and when you use a function like malloc it allocates a free memory block for you and the pointer points to the first position of the block. Now that block will only return to the free block list when you free it. So once you have finished using that memory location you should free it.
When you did:
temp = NULL;
free(temp);
You were trying to free the NULL memory position, which does not make sense.
So you are only going to free a memory once you do not need it anymore.
I suggest you search more about variables and pointers in the C language, this link might help you:
enter link description here
I am new to C programming. I am trying to do the pset5 in CS50 while trying to understand the concepts of memory, linked list and hashtable. I wrote the code and it compiled but there seems to be something wrong because every time I tried to execute the code it returns some garbage value. Could anyone please help me with that? Many thanks.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#include "dictionary.h"
#define DICTIONARY "dictionaries/small"
typedef struct node
{
char WORD[LENGTH + 1];
struct node *next;
}
node;
int hash(char *word);
int main(void)
{
node **HASHTABLE = malloc(sizeof(node) * 26);
//open the dictionary
FILE *dic = fopen(DICTIONARY, "r");
if (dic == NULL)
{
fprintf(stderr, "Could not open the library\n");
return 1;
}
int index = 0;
char word[LENGTH + 1];
for (int c = fgetc(dic); c != EOF; c = fgetc(dic))
{
word[index] = c;
index++;
if (c == '\n')
{
int table = hash(word);
printf("%d\n", table);
//create a newnode
node *newnode = malloc(sizeof(node));
strcpy(newnode->WORD, word);
newnode->next = NULL;
printf("Node: %s\n", newnode->WORD);
index = 0;
//add new node to hash table
if (HASHTABLE[table] == NULL)
{
HASHTABLE[table] = newnode;
}
else
{
HASHTABLE[table]->next = newnode;
}
}
}
for(int i = 0; i < 26; i++)
{
node *p = HASHTABLE[i];
while (p != NULL)
{
printf("%s", p->WORD);
p = p->next;
}
}
//free memory
for(int i = 0; i < 26; i++)
{
node *p = HASHTABLE[i];
while (p != NULL)
{
node *temp = p->next;
free(p);
p = temp;
}
}
free(HASHTABLE);
}
int hash(char *word)
{
int i = 0;
if (islower(word[0]))
return i = word[0] - 'a';
if (isupper(word[0]))
return i = word[0] - 'A';
return 0;
}
Your code has serious problems that result in undefined behavior.
Two of them are the result of this line:
node **HASHTABLE = malloc(sizeof(node) * 26);
That allocates 26 node structures, but the HASHTABLE variable expects the address of a pointer to an array of node * pointers (that's the ** in the node **HASHTABLE declaration).
So, you should replace it with something like:
node **HASHTABLE = malloc( 26 * sizeof( *HASHTABLE ) );
Note that I used the dereferenced value of the variable being assigned to - HASHTABLE. This means in this case a node (one less * than in the declaration). So if the type of HASHTABLE changes, you don't need to make any other changes to the malloc() statement.
That problem, while technically undefined behavior, likely wouldn't cause any problems.
However, there's still a problem with
node **HASHTABLE = malloc( 26 * sizeof( *HASHTABLE ) );
that will cause problems - and serious ones.
That array of 26 pointers isn't initialized - you don't know what's in them. They can point anywhere. So this won't work well, if at all:
if (HASHTABLE[table] == NULL)
Meaning this points off to somewhere unknown:
HASHTABLE[table]->next = newnode;
And that will cause all kinds of problems.
The simplest fix? Initialize the values all to zero by using calloc() instead of malloc():
node **HASHTABLE = calloc( 26, sizeof( *HASHTABLE ) );
Until that's fixed, any results from your entire program are questionable, at best.
The reason for the garbage is that you didn't null-terminate the string:
strcpy(newnode->WORD, word);
strcpy expects the src to point to a null-terminated string. Simply adding 0 at the end. Simply terminate it with
word[index] = 0;
before the strcpy.
Other than that, the ones in Andrew Henle's answer should be addressed too, but I am not going to repeat them here.
BTW, next you will notice that
HASHTABLE[table]->next = newnode;
wouldn't work properly - that code always inserts the node as the 2nd one. But you want to always insert the new node unconditionally as the head, with
newnode->next = HASHTABLE[table];
HASHTABLE[table] = newnode;
There need not be any special condition for inserting the first node to a bucket.
I am reading from txt file into a doubly linked list. The codes can do storing data into Nodes, but when I let it go through the linked list, it got a segmentation fault.
Could you guys please tell what has been wrong with the code, thank you!
This is the data structure:
typedef struct telephoneBookNode {
int id;
char name[NAME_LENGTH];
char telephone[TELEPHONE_LENGTH];
struct telephoneBookNode * previousNode;
struct telephoneBookNode * nextNode;
} TelephoneBookNode;
typedef struct telephoneBookList {
TelephoneBookNode * head;
TelephoneBookNode * tail;
TelephoneBookNode * current;
unsigned size;
} TelephoneBookList;
This is the code to create linked list:
TelephoneBookList * createTelephoneBookList(char entry[]) {
TelephoneBookList* aList = NULL;
TelephoneBookNode* aNode = NULL;
char *tokens;
TelephoneBookNode *(*create)() = createTelephoneBookNode;
aNode = (*create)();
tokens = strtok(entry, ", ");
aNode->id = atoi(tokens);
tokens = strtok(NULL, ", ");
strcpy(aNode->name, tokens);
tokens = strtok(NULL, ", ");
strcpy(aNode->telephone, tokens); //Fine until here
//Do I need this line?
//aList = (TelephoneBookList*) malloc(aList->size + 1) * sizeof aList);
if (aList->head == NULL) {
aNode->nextNode = NULL;
aNode->previousNode = NULL;
aList->current = aNode;
aList->head = aNode;
aList->tail = aNode;
} else {
aList->tail->nextNode = aNode;
aNode->previousNode = aList->tail;
}
return aList;
}
TelephoneBookNode * createTelephoneBookNode() {
TelephoneBookNode* aNode;
aNode = (TelephoneBookNode*) malloc(sizeof *aNode);
return aNode;
}
//Do I need this line?
//aList = (TelephoneBookList*) malloc(aList->size + 1) * sizeof aList);
Yes. Yes you do need that line. Otherwise the next line
if (aList->head == NULL) {
will dereference a null pointer.
Though you already do that in the commented out malloc call, dereference a null pointer, with aList->size + 1.
The correct line should be
aList = malloc(sizeof *aList);
And since you create the list from scratch in the function, there is no need to check if it is empty or not, it will always be empty. More importantly, the malloc call will not initialize the memory it allocates, so using that memory (for example in an expression like aList->head == NULL) will lead to undefined behavior.
Allocate the list structure. And then initialize it as if it was empty. And don't forget to initialize the size member as well.
Your createTelephoneBookNode function does not initialize the node that it created. malloc() assigns it a memory block that's probably not been initialized with zeros, and as a result, the nextNode and previousNode pointers contain garbage. Either set them both to NULL, or allocate your memory with calloc().
I trying to write a queue(String Version) program in C by using linked lists.
Here is the structure:
struct strqueue;
typedef struct strqueue *StrQueue;
struct node {
char *item;
struct node *next;
};
struct strqueue {
struct node *front;//first element
struct node *back;//last element in the list
int length;
};
I creates a new StrQueue first
StrQueue create_StrQueue(void) {
StrQueue q = malloc(sizeof (struct strqueue));
q->front = NULL;
q->back = NULL;
q->length = 0;
return q;
}
makes a copy of str and places it at the end of the queue
void push(StrQueue sq, const char *str) {
struct node *new = malloc(sizeof(struct node));
new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?
new->next = NULL;
if (sq->length == 0) {
sq->front = new;
sq->back = new;
} else {
sq->back->next = new;
sq->back = new;
}
sq->length++;
}
frees the node at the front of the sq and returns the string that was first in the queue
char *pop(StrQueue sq) {
if (sq->length == 0) {
return NULL;
}
struct node *i = sq->front;
char *new = sq->front->item;
sq->front = i->next;
sq->length --;
free(sq->front);
return new;
}
I got invalid write size of 1 at strcpy(new->item,str); I dont understand why I got this error.
Can anyone tell me why and tell me how should I fix it? Thanks in advance.
Okay, first things first, in the answer below I am NOT fixing your doubly linked list concepts, I am just showing you how you should fix the code above within the scope of your question. You may want to look into how doubly linked lists are done.
In:
void push(StrQueue sq, const char *str) {
struct node *new = malloc(sizeof(struct node));
new->item = NULL;
The next statement is wrong:
strcpy(new->item,str);
There are two ways you can solve it:
Make sure that *str is a valid pointer outside of the list management context while the list is being used.
Let the list manage the string allocation (and possibly deallocation).
is the quick and dirty method, it's easier to debug later but larger codebase makes it cumbersome.
cleaner looking code, but requires initial setup discipline, you should create object (string) management routines in addition to list management routines. can be cumbersome in its own right.
CASE 1: const char *str is guaranteed to be valid for life of StrQueue (this is what you are looking for really)
It should be:
new->item = str;
Here we assume str was a dynamic string allocated elsewhere
Now, in pop when you pop off the string you are okay. because the pointer you are returning is still valid (you are guaranteeing it elsewhere)
CASE 2: const char *str is not guaranteed to be valid for life of StrQueue
Then use:
new->item = strdup(str);
Now, in pop when you pop off the string you can either
de-allocate the strdup and not return anything, (not quite the same things as you did)
pass a container pointer to pop where contents of item are copied (clean)
return the popped off pointer, but you must deallocate it separately when you are done with it (ugly)
Which would make your pop function one of the following:
Case 2.1:
void pop(StrQueue sq) {
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
free(node->item);
free(node);
}
Case 2.2:
char *pop(StrQueue sq, char *here) {
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
strcpy(here, node->item);
free(node->item);
free(node);
}
Case 2.3:
char *pop(StrQueue sq) {
char *dangling_item = NULL;
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
dangling_item = node->item;
free(node);
return dangling_item;
}
I got invalid write size of 1 at strcpy(new->item,str); I dont understand why I got this error. Can anyone tell me why and tell me how should I fix it?
Why:
This code:
new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?
You're not suppose to pass a null pointer to the first argument, it should be a pointer to allocated memory. The reason why you're getting this error message, I can imagine, is because the implementation of strcpy probably looks like this:
for (int i = 0; str2[i]; i++) str1[i] = str2[i];
And in the first iteration of the for loop, it writes to address 0 (a read-only section of memory) - this gives you the invalid write of size 1. I'm not sure, however, why you are only getting a size of 1, though (I would imagine it would be the entire size of the string). This could be because either a) str is only of size 1 or b) because the signal, SIGSEGV stops the program.
How to fix:
Allocate space for new->item before calling strcpy, like this:
new->item = malloc (strlen (str) + 1); // + 1 for null-terminating character
But you could probably include some error checking, like this:
int len = strlen (str) + 1;
if (len){
new->item = malloc (len);
if (!new->item){
return;
}
}
Just trying to make a kind of hash table with each node being a linked list.
Having trouble just initializing the space, what am I doing wrong?
#include <stdlib.h>
typedef struct entry {
struct entry *next;
void *theData;
} Entry;
typedef struct HashTable {
Entry **table;
int size;
} HashTable;
int main(){
HashTable *ml;
ml = initialize();
return 0;
}
HashTable *initialize(void)
{
HashTable *p;
Entry **b;
int i;
if ((p = (HashTable *)malloc(sizeof(HashTable *))) == NULL)
return NULL;
p->size = 101;
if ((b = (Entry **)malloc(p->size * sizeof(Entry **))) == NULL)
return NULL;
p->table = b;
for(i = 0; i < p->size; i++) {
Entry * b = p->table[i];
b->theData = NULL;
b->next = NULL;
}
return p;
}
You need to change sizeof(HashTable*) to sizeof(HashTable) and similarly sizeof(Entry **) to sizeof(Entry *) . And the second thing is for every Entry you need to allocate memory using malloc again inside the loop.
if ((p = malloc(sizeof(HashTable))) == NULL)
return NULL;
p->size = 101;
if ((b = malloc(p->size * sizeof(Entry *))) == NULL)
return NULL;
I believe removing the malloc() result casts is best practice.
Plus, as #Naveen was first to point out you also need to allocate memory for each Entry.
Firstly your sizeofs are wrong. T * = malloc( num * sizeof(T)) is correct. You can also use calloc.
You are reusing b for different purposes so it is quite confusing. Not generally good using a single character variable.
p->table which was b is allocated but not initialised, i.e. it doesn't point to anything useful, then you are trying to dereference it.
You need to fill it will Entry* pointers first, and they must be pointing to valid Entry structs if you are going to dereference those.
Your process probably dies on the line b>theData = NULL
Also, you can statically declare your HashTable, either locally, or in some region high enough in the stack that the stack is non-ascending (in memory) while it is used and pass a pointer to the HashTable to your initialize function to avoid a malloc. malloc is slow.
So in main, you can do:
HashTable table;
InitializeHashTable(&table);
// use table (no need to free)
// just do not return table