Problem with a linked list - c

I have a problem with this small program. It added some value to list. If I uncomment //printf("%d",first->val); the program gives error. Everything seems to be ok ;(
#include <stdio.h>
#include <stdlib.h>
typedef struct element {
struct element *next;
int val;
} el_listy;
el_listy *first = 0;
void add_to_list(el_listy *lista, int value)
{
if(lista == 0)
{
lista = malloc (sizeof(el_listy));
lista->val = value;
lista->next = 0;
printf("added as first \n");
}
else
{ printf("added as fsecond \n");
el_listy *wsk = lista,*tmp;
while(wsk->next != 0) wsk = wsk->next;
tmp = malloc (sizeof(el_listy));
tmp->val = value;
tmp->next = 0;
wsk->next = tmp;
}
}
int main ()
{
add_to_list(first,2);
add_to_list(first,4);
//printf("%d",*first->val);
system("pause");
return 0;
}

first->val is just like (*first).val, you can't use them both. also, as missingno said, add_to_list never changes first you should pass it's address as argument, not the pointer itself, meaningadd_to_list(&first,4); (and change the implementation of add_to_list as well)

Your program never changes the value of first. It remains a null pointer and thus gives an error when dereferenced.

-> already follows a pointer, so the * tries to treat first as pointer to pointer to el_listy. You might find cdecl helpful.

You should use either (*first).val or first->val. Otherwise you get the wrong level of indirection.

Yes, it's a simple mistake.
fitsr won't change after *add_to_list()* function is called.
You should define function like this:
add_to_list(El_list **lista, ...)

Related

i am trying to read and print one value in a linked list , but my program does not give any output

i am trying to read and print one value in a linked list , but my program does not give any output, i have tryed checking where the program is failing to execute , after the first scanf the code is not printing anything, what might be the reason for that?
code is as followed:
#include<stdlib.h>
#include<stdio.h>
void display();
struct ll{
int val;
struct ll* address;
};
struct ll *new=NULL,*start=NULL,*present=NULL;
int main(void)
{
int num;
scanf("%d",&num);
//reading ll
new=(struct ll*) malloc(sizeof(struct ll));
new->val=num;
new->address=NULL;
if(start==NULL)
{
start=new;
present=new;
}
else
{
present->address=new;
present=new;
}
//calling display func to display the contents of ll
display();
}
void display()
{
present=start;
// displaying.
while (present!=NULL)
{
printf("%d",present->val);
present=present->address;
}
printf("%d",present->val);
}
I have encoded my comments interspersed into your code. I have commented the last statement in function display(), to make it run properly. I have also commented the cast to malloc() (for the given reasons in the code) I have also made some aesthetic changes to make the code more readable. You can add spaces to improve readability of the code, as they don't change the compiler produced code, so please, use enough spaces to make your code more readable (I've done this also to show who it is more readable now):
#include <stdlib.h>
#include <stdio.h>
void display(void);
struct ll {
int val;
struct ll *address;
};
struct ll *new = NULL,
*start = NULL,
*present = NULL;
int main(void)
{
int num;
scanf("%d", &num);
//reading ll
/* Never cast the returned value of malloc() This allows to
* detect if you have properly #include'd the header file and
* avoids other dificult to find errors. malloc() returns a
* void * pointer, so it will be automatically converted to
* any other pointer type without risk. */
new = /* (struct ll*) */ malloc(sizeof(struct ll));
new->val = num;
new->address = NULL;
if(start == NULL)
{
start = new;
present = new;
}
else
{
/* this is never executed, as start == NULL at program
* start. */
present->address = new;
present = new;
}
//calling display func to display the contents of ll
display();
/* while it is not necessary for main() it is normal for a function
* that is defined to return an int value, to return something, so
* I added the following statement: */
return 0;
}
void display(void)
{
present = start;
// displaying.
while (present != NULL)
{
printf("%d",present->val);
present = present->address;
}
/* as you have moved present in a while loop until the while
* condition is false, at this point you must assume the
* condition is false (so present == NULL) and you are trying to
* dereference a NULL pointer below */
/* printf("%d", present->val); */
}
Now your program will run and show the only value (I recommend you to put a \n character at the end of the printf() call, to put the printed data in a line by itself.

Struct passed from pointer shows wrong values

I have a variable struct employee which I initialized on the heap using malloc. I am passing this variable from a pointer using *tmp as shown bellow. The problem is that the values of the variable once passed to the function are wrong. I assume this has to do with the pointer but I can't find the mistake. I guess I am forgeting a basic about pointers. To me, I am passing the variable struct employee pointed by *tmp (and not its address as passing the pointer would do). Can't see what's wrong in there.
If I check the value inside the createEmployee() function or after calling it, they are right, but they are not in isInformationValid(employee e). If I change my code and pass a pointer to the function, everything works all right.
typedef struct employee{
char nom[MAX_NAME_LEN];
char prenom[MAX_NAME_LEN];
unsigned short badge;
unsigned long secret;
time_t lastAccess;
} employee;
typedef struct maillon maillon;
struct maillon{
maillon* next;
maillon* prev;
employee* e;
};
typedef struct e_list{
maillon* m;
} e_list;
[...]
int isInformationsValid(employee e){
int invalidName = (strlen(e.nom) <= 2 || strlen(e.prenom) <= 2); // Problem here
int invalidBadge = (e.badge < 1000 || e.badge > 9999); // Problem here. e.badge taken as "25789" when I input "1010"
if(invalidName) { errno = EPERM; perror("Name length must be > 2"); return -1; }
if(invalidBadge) { errno = EPERM; perror("Badge must be 4 digits"); return -1; }
return 0;
}
employee* createEmployee(){
employee* tmp = calloc(1, sizeof(employee*));
getString("A man needs a last name : ", tmp->nom, MAX_NAME_LEN);
getString("A man needs a first name : ", tmp->prenom, MAX_NAME_LEN);
getDigits("Badge (4 digit) : ", &tmp->badge, "%hu");
getDigits("Secret : ", &tmp->secret, "%lu");
time_t t = time(NULL);
tmp->lastAccess = t;
if(isInformationsValid(*tmp) == -1){ // Passing addr of the struct
return NULL;
}
return tmp;
}
What did I miss? Did I do something wrong in any initialization or am I missing a basic thing about pointers ?
I saw that other questions on stackoverflow has similar questions
The only answers I could reading those other questions was forgotten dynamic allocations on the heap, which is what I think I am doing (maybe the wrong way tho).
EDIT
I was doing it wrong.
You are allocating the size of an employee *, but you should be allocating the size of an employee (or *tmp).

Abort trap 6 malloc

I am trying to make an implementation of an n-ary tree in C. When running it I get the following error:
sibling(1143,0x7fff7e925000) malloc: *** error for object 0x7f946b4032c8: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
I am unsure what is causing the error. As it says it seems that I am writing to an object that was freed. But in my code I do not free any of the memory allocated. I am new to c to this confused me very much. I tried debugging with gdb and it says the error is caused by the printTree(); call in main where I am recursively trying to print the tree. Hope you can help me understand the issue :-).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
unsigned int utility;
unsigned int probability;
} Child;
typedef struct {
unsigned int level;
unsigned int player;
unsigned int nChildren;
Child *children;
} Data;
typedef struct sNaryNode{
Data *data;
struct sNaryNode *kid;
struct sNaryNode *sibling;
} NaryNode;
NaryNode* createNode(Data data){
NaryNode *newNaryNode = malloc(sizeof (NaryNode*));
newNaryNode->sibling = NULL;
newNaryNode->kid = NULL;
newNaryNode->data = &data;
return newNaryNode;
}
NaryNode* addSibling(NaryNode* n, Data data){
if(n == NULL) return NULL;
while(n->sibling)
n = n->sibling;
return (n->sibling = createNode(data));
}
NaryNode* addChild(NaryNode* n, Data data){
if(n == NULL) return NULL;
else if(n->kid)
return addSibling(n->kid, data);
else
return (n->kid = createNode(data));
}
void printTree(NaryNode* n) {
if(n == NULL) return;
if(n->sibling) {
printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name);
printTree(n->sibling);
}
else if(n->kid) {
printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name);
printTree(n->kid);
}
else {
printf("The tree was printed\n");
}
}
int main(void) {
NaryNode *root = calloc(1, sizeof(NaryNode));
Data data;
data.level = 1;
data.player = 1;
data.nChildren = 2;
data.children = calloc(data.nChildren, sizeof data.nChildren);
data.children[0].probability = 50;
data.children[0].utility = 1;
data.children[0].name = "Kom med det første tilbud (anchor)";
data.children[1].probability = 50;
data.children[1].utility = 1;
data.children[1].name = "Afvent modspilleren kommer med første tilbud";
*root = *createNode(data);
int i = 0;
for(i=0; i<root->data->nChildren; i++) {
addChild(root, data);
}
printTree(root);
}
There are various errors in your code.
Allocating an incorrectly sized memory block :
data.children = calloc(data.nChildren, sizeof data.nChildren);
data.children is an array of Child structures, yet you're allocating structures whose size is equal to sizeof(unsigned int), due to data.nChildren being an unsigned int.
Taking the address of a temporary variable and storing it for later usage :
NaryNode* createNode(Data data){
newNaryNode->data = &data;
}
data in createNode only exists for as long as the function is running : in this case, you're taking the address of the local variable data and storing it in the structure that you're returning for later usage. This is a very bad idea, since this pointer will refer to an object that doesn't exist anymore after the function returns.
Keep in mind that you don't need to pass a copy of the Data object into createNode in your current code, since there is really only one Data object in the whole program. Thus, you can change the prototype of createNode to createNode(Data* data), and pass the address of the Data structure that you create in main. Doing anything more involved than that, though, would require deep-copying the structure, I think.
Incorrectly managing the objects' lifetime.
NaryNode *root = calloc(1, sizeof(NaryNode));
*root = *createNode(data);
createNode returns an NaryNode*. However, you never actually assign it to an NaryNode* so that you can free it later. Instead, the pointer to the object that the function returns is known only during the *root = *createNode(data) invocation, and irrevocably lost later on. You do, however, retain the contents of the object due to dereferencing it and copying it into root : the object itself, however, as returned from createNode, is lost and not recoverable, unless pointers to it still exist in the tree.
Here is another problem. This line does not allocate space for a NaryNode, but only for a pointer to a NaryNode:
NaryNode *newNaryNode = malloc(sizeof (NaryNode*));

Freeing linked list in C

Hi I was trying to write a function that takes in the head of a linked list and free all the memory it allocated. Here is the original code I wrote.
void clear_nodes(List *h) {
if (!h->next) {
free(h);
***h = NULL;***
}
else {
clear_nodes(h->next);
clear_nodes(h);
}
}
However it does not work. So I changed it to
void clear_nodes(List *h) {
if (!h->next) {
free(h);
}
else {
clear_nodes(h->next);
***h->next = NULL;***
clear_nodes(h);
}
}
and now it worked.
Notice the difference between the two, I just wonder why can't I make the pointer to null directly. Is it because it's a local variable or something? But marking a pointer to null should make the pointer point to some memory address that I can't access right? Why would it matter if I do it locally or globally.
Thank you guys in advance.
I would probably do this NON-RECURSIVELY
void clear_nodes(List **h) {
List * copy = *h;
while( (copy = (*h)->next) != NULL){
free(*h);
*h = NULL;
*h = copy;
}
}
Recursivity is generally slower than looping. If you can try to design without recursive routines.
Since the value of h was passed, and not the location, you are not changing the pointer - you are changing a copy of the pointer.
If you changed your function to
void clear_nodes(List **h) {
if ((*h)->next == NULL) {
free(*h);
*h = NULL;
}
else {
clear_nodes(&((*h)->next));
clear_nodes(h);
}
}
You could change it "locally". I think I got that second part right... didn't try to compile / run it. I am positive about the first part though.

C - Passing a Pointer to a Function and then Passing that Same Pointer Inside the Function to Another Function

Whew! Long title...here's some pseudo-code to explain that verbiage:
int main(){
int* ptr = function1(); //the data that ptr points to is correct here
function2(ptr);
}
int function2(int* ptr){
//the data that ptr points to is still correct
int i;
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); //since ptr points to a contiguous block of memory
function3(ptr);
}
int function3(int* ptr){
//the data that ptr points to is INCORRECT!!!
}
Why would the data in function3 be incorrect?
Note: function1 performs a malloc() and returns the pointer to that memory.
ACTUAL CODE
#include <stdlib.h>
#include <stdio.h>
//Structures
struct hash_table_data_
{
int key, data;
struct hash_table_data_ *next, *prev;
};
struct hash_table_
{
int num_entries;
struct hash_table_data_ **entries;
};
typedef struct hash_table_data_ hash_table_data;
typedef struct hash_table_ hash_table;
//Prototypes
hash_table *new_hash_table(int num_entries);
int hash_table_add(hash_table *ht, int key, int data);
int hash_table_loader(hash_table* ht);
//Main
int main()
{
int num_entries = 8;//THIS MUST BE AUTOMATED
hash_table* ht = new_hash_table(num_entries);
hash_table_loader(ht);
return 0;
}
//Function Definitions
hash_table *new_hash_table(int num_entries)
{
hash_table* ht = (hash_table*) malloc(sizeof(hash_table));
hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
int i;
for (i=0;i<num_entries;i++)
{
array[i].key = -1;
array[i].data = -1;
array[i].next = NULL;
array[i].prev = NULL;
}
ht->entries = &array;
ht->num_entries = num_entries;
return ht;
}
int hash_table_add(hash_table *ht, int key, int data)
{
//VERIFY THAT THE VALUE ISN'T ALREADY IN THE TABLE!!!!!!!!!!!
int num_entries = ht->num_entries;
hash_table_data* array = *(ht->entries); //array elements are the LL base
int hash_val = key%num_entries;
printf("adding an element now...\n");
printf("current key: %d\n", array[hash_val].key);
int i;
for(i=0;i<num_entries;printf("%d\n", (*(ht->entries))[i].key),i++);//DATA IS INCORRECT!!!!
if (array[hash_val].key == -1)//is this the base link?
{
printf("added a new base link!\n");
array[hash_val].key = key;
array[hash_val].data = data;
array[hash_val].next = NULL;
array[hash_val].prev = &(array[hash_val]);
}
else//since it's not the base link...do stuff
{
hash_table_data* new_link = malloc(sizeof(hash_table_data));
new_link->key = key;//set the key value
new_link->data = data;//set the data value
if (array[hash_val].next == NULL)//we must have the second link
{
printf("added a new second link!\n");
new_link->prev = &(array[hash_val]); //set the new link's previous to be the base link
array[hash_val].next = new_link; //set the first link's next
}
else//we have the 3rd or greater link
{
printf("added a new 3rd or greater link!\n");
hash_table_data next_link_val = *(array[hash_val].next);
while (next_link_val.next != NULL)//follow the links until we reach the last link
{
next_link_val = *(next_link_val.next);//follow the current link to the next
}
//now that we've reached the last link, link it to the new_link
next_link_val.next = new_link; //link the last link to the new link
new_link->prev = &(next_link_val); //link the new link to the last link
}
}
return 0;
}
int hash_table_loader(hash_table* ht)
{
int i;
for(i=0;i<(ht->num_entries);printf("%d\n", (*(ht->entries))[i].key),i++); //DATA IS STILL CORRECT HERE
FILE *infile;
infile = fopen("input.txt", "r");
while(!feof(infile))
{
int key,data;
fscanf(infile, "%d %d", &key, &data);
hash_table_add(ht, key, data);
}
fclose(infile);
}
Note: Issue occurring the first time hash_table_add() is called.
Your first problem is here:
ht->entries = &array;
You cause the structure to hold a hash_table_data** which points to the variable hash_table_data* array which is local to the function; then you exit the function and return a pointer to the structure. The structure still exists (it was allocated via malloc(), and the stuff that array points to still exists, but array itself does not. Accordingly, this pointer within the structure is now invalid.
As far as I can tell, there is no reason for you to be holding a pointer-to-pointer here. Just use hash_table_data* as the entries type, and copy array into that struct member. Pointers are values too.
I guess you iterate incorrectly
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++);
this is nonsense.
You should rewrite it as this:
for(i=0;i<length;i++)
printf("%d\n", ptr[i]);
(*ptr)[i] is just wrong, it doesn't make sense if you think about it.
*ptr is the first element of the pointed-to array of ints.
ptr[i] is thi ith one, this is what you need.
Please, read Section 6 carefully.
A couple of advises based on this question:
Don't write overcomplicated code like this for statement with comma operator used, it just rarely needed and leads not only to confusion, but to mistakes (although no mistakes with it in this particular example)
Look carefully for mistakes, don't blame everything on functions. If your code doesn't work, try finding the exact place which is wrong and prove it. In this example people who tested your code were right: functions are definitely not the cause of the error.
hash_table *new_hash_table(int num_entries)
{
hash_table* ht = (hash_table*) malloc(sizeof(hash_table));
hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
// ....
ht->entries = &array; // Problem
// ...
return ht;
} // Life time of array ends at this point.
You are taking the reference of the local variable array and assigning it to ht->entries which is no more valid once the function returns.

Resources