C order of elements in a struct - c

I am pretty new to C and I was wondering if the order of elements in a struct matter.
I have the following struct:
struct list
{
struct list_el *head;
int size;
}
I use this to make a linked list. The head points to the first element and the size shows the amount of elements in the list.
I have also have the following function to initialize the list.
typedef struct list list;
list* list_init()
{
list *list = malloc(sizeof(list));
if(list)
{
list->head = NULL;
list->size = 0;
return list;
}
return NULL;
}
The program compiles fine, without any errors, warnings or notes, but when I run the program using valgrind it says I have an invalid write of size 4 on the line in the list_init() function where I assign 0 to list->size. I have the same invalid read/write every time I access the size variable. I have no idea why. Also when I switch the two struct elements around (declare size first and then head) I get the invalid write on the line where I assign NULL to head and then the size variable is used just fine. Can anybody explain me why this happens and how I can fix it?
Last note: the struct as it is shown here is defined in an header file while the function is in the C file. Not sure if this is important.

You named the variable with the same name as the type, so sizeof(list) is implemented as the size of the variable (pointer), not the size of the struct. The struct has a pointer and a integer, so the size will be larger than a pointer, so access to not allocated place occurred.
Rename the variable.
example:
list *list_init(void)
{
list *list_data = malloc(sizeof(list));
if (list_data)
{
list_data->head = NULL;
list_data->size = 0;
return list_data;
}
return NULL;
}

Related

Why do I get the memory access violation error using pointer to pointer

I created a small program in C to test pointer to pointer.
When I use a function (line 39) to print a list data, after adding an item to the list I get error 3221225477. However, when I comment the line 39, and I remove the comment from line 59 the program works normally.
Why do I get a ACCESS_VIOLATION error from the operating system, in this case Windows, if the program is running from top to bottom?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
struct employee{
int id;
char name[50];
char street[50];
};
typedef struct element* List;
struct element{
struct employee data;
struct element *next;
};
typedef struct element Elem;
List* list_create();
void list_print(List* list);
int list_is_empty(List* list);
int list_add(List* list, struct employee a);
int main(){
List* list = list_create();
struct employee a1;
a1.id = 10;
strcpy(a1.name, "John");
strcpy(a1.street, "Address XYZ");
list_add(list, a1);
//Sleep(5000); small pause, I thinking it might have something to do with thread.
//list_print(list); // *****line--39 *****;
return 0;
}
List* list_create(){
List* li = (List *) malloc(sizeof(List));
if(li != NULL)
*li = NULL;
return li;
}
int list_add(List* list, struct employee emp){
Elem* n1 = (Elem *) malloc(sizeof(Elem));
n1->data = emp;
n1->next = *list;
list = &n1;
list_print(list); // *****line--59 *****;
}
void list_print(List* list){
Elem aux = **list;
printf(" **lista Id: %d\n", aux.data.id);
printf(" **lista name: %s\n", aux.data.name);
printf(" **lista name: %s\n", aux.data.street);
}
C is pass-by-value, not pass-by-reference. Thus, the List* list in the function list_add and the List* list in main refer to two different locations in memory (they initially point to the same place at the start of list_add, but they are two different pointers with initially the same value, not the same pointer): modifying the value of the variable list within list_add does not affect the value of list in main.
To be specific:
list = &n1 in list_add modifies only the value of list within that function, i.e. the argument value that was copied into list_add's stack frame on invocation. However, when you try to print it on line 59, still within list_add, the changed value is seen and is thus the pointer printed from, working as you expect.
When you try to print list on line 39, in main, on the other hand, the variable list within the main function did not have its value changed by the assignment list = &n1 just before line 39 in list_add, since that only changed the value of the copy in that function's scope. Thus in that case list_print tries to print elements of an empty list (since the value of list is still just what was returned by list_create, which is a pointer to a NULL pointer, and so Elem aux = **list thus dereferences list and then tries to dereference a NULL pointer) and thus leads to an invalid memory access.
The problem in this code, then, is not the placement of the list's printing but rather that list_add is not updating the list properly. In fixing this you need to take into account that it can only modify the list structure by modifying what the reference value it received as an argument is pointing to, rather than by trying to modify the pointer itself. If you do want to modify the address list points to in main from within the function list_add (such as what the line list = &n1 seems to be attempting to do), you would need to pass a pointer to list into list_add, rather than just the pointer list itself.
There appear to be other issues in the code itself (list_print prints only one element and has no handling for printing empty lists, for example, which is what causes the error here to be an actual invalid memory access instead of merely incorrectly leaving the list empty after calling list_add), but the issue described above is the cause of this particular problem.

Why use dynamic memory allocation(i.e. malloc()) when implementing linked list in c?

Okay this question may sound stupid to the amateur programmers . But seriously this is bothering me and a solemn answer to this doubt of mine is welcomed. I have just started to take my first ever course in data structures. And what is bothering me is this:
Assuming C is used,
//Implementing a node
struct Node
{
int data;
struct *Node;
};
Now while creating a node why do we use the dynamic memory allocation technique where we use malloc(). Can't we just create a variable of type ' Struct Node '.
i.e. something like:
struct Node N1;
//First node - actually second where !st Node is assumed to be Head.
struct Node *Head = &N1;
struct Node N2;
N2.(*Node) = &N1;
Well some parts of my code may be incorrect because I am only a beginner and not well versed with C. But by know you may have understood what I basically mean. Why don't we create variables of type Node of an Array of type Node to allocate memory t new nodes why get into the complexity of dynamic memory allocation?
First off, you have an error in how you declare your struct. struct * by itself does not denote a type. You have to give the full type name:
struct Node
{
int data;
struct Node *Node;
};
You can certainly use local variables as above to make a linked list, however that limits you to a fixed number of list elements, i.e. the ones you explicitly declare. That would also mean you can't create a list in a function because those variables would go out of scope.
For example, if you did this:
struct Node *getList()
{
struct Node head, node1, node2, node3;
head.Node = &node1;
node1.Node = &node2;
node2.Node = &node3;
node3.Node = NULL;
return &head;
}
Your list would be restricted to 4 elements. What of you needed thousands of them? Also, by returning the address of local variables, they go out of scope when the function returns and thus accessing them results in undefined behavior.
By dynamically allocating each node, you're only limited by your available memory.
Here's an example using dynamic memory allocation:
struct Node *getList()
{
struct Node *head, *current;
head = NULL;
current = NULL;
// open file
while (/* file has data */) {
int data = /* read data from file */
if (head == NULL) { // list is empty, so create head node
head = malloc(sizeof(struct Node *));
current = head;
} else { // create new element at end of list
current->next = malloc(sizeof(struct Node *));
current = current->next;
}
current->data = data;
current->Node = NULL;
}
// close file
return head;
}
This is psedo-code that doesn't go into the details of reading the relevant data, but you can see how you can create a list of arbitrary size that exists for the lifetime of the program.
If these variables are local, defined inside a function's scope (i.e. stored on the stack), you shouldn't do this, because accessing them after leaving their scope will result in undefined behavior (their contents will likely be overwritten as you call other functions). In fact, any time you return a pointer to a local, stack based variable from your function, you are doing the wrong thing. Given the nature of C, this is problematic since nothing will warn you you are doing something wrong, and it will only fail later when you try to access this area again.
On the other hand, if they are declared as global variables (outside any other function), then you are simply limited by the number of variables declared that way.
You can potentially declare many variables, but keeping track of which one is "free" for use will be painful. Sure, you can even go a step further and say you will have a global preallocated array of nodes to prevent using malloc, but as you are doing all this you are only getting closer to writing your own version of malloc, instead of sticking to the existing, dynamic one.
Additionally, all preallocated space is wasted if you don't use it, and you have no way of dynamically growing your list in runtime (hence the name dynamic allocation).
Here is some good reasons to use dynamic memory
When you declare node struct Node N1;this node will store on stack memory. After scope of the node that will get destroy auto.But in case of dynamic you have handle to free the memory when you done.
When you have some memory limitation.
When you don't know the size of array then dynamic memory allocation will help you.
One issue could be that you cannot use another function to add a new node to your list.
Remember that automatic variables - like the ones created by struct Node node100; - have scope only inside the function in which they are defined. So when you do something like this:
int main()
{
struct Node *head;
/* Some code there you build list as:
head ---> node1 ---> node2 --> .. ---> node99
*/
/* Add a new node using add_node function */
add_node(head, 555);
/* Access the last node*/
}
void add_node(struct Node *head, int val)
{
/* Create new node WITHOUT using malloc */
struct Node new_node;
new_node.data = val;
/* add this node to end of the list */
/* code to add this node to the end of list */
/* last_element_of_list.next = &new_node*/
return;
}
Now you think that you have added a new node to the end of the list. But, unfortunately, its lifetime ends as soon as the add_node function returns. And when you try to access that last node in your main function your program crashes.
So, to avoid this situation you will have put all your code in one single function - so that the lifetime of those nodes do not end.
Having all your code in ONE function is bad practice and will lead to many difficulties.
This was one situation that asks for a dynamic memory allocation, because, a node allocated with malloc will be in scope untill it is freed using free, and you can put code that do different things in different functions, which is a good practice.
You don't have to use dynamic memory to create a linked list, although you definitely don't want to create separate variables for each node. If you want to store up to N items, then you'd need to declare N distinct variables, which becomes a real pain as N gets large. The whole idea behind using a linked list is that it can grow or shrink as necessary; it's a dynamic data structure, so even if you don't use malloc and free, you're going to wind up doing something very similar.
For example, you can create an array of nodes at file scope like so:
struct node {
int data;
struct node *next;
};
/**
* use the static keyword to keep the names from being visible
* to other translation units
*/
static struct node store[N]; /* our "heap" */
static struct node *avail; /* will point to first available node in store */
You the initialize the array so each element points to the next, with the last element pointing to NULL:
void initAvail( void )
{
for ( size_t i = 0; i < N - 1; i++ )
store[i].next = &store[i + 1];
store[N - 1].next = NULL;
avail = store;
}
To allocate a node for your list, we grab the node avail points to and update avail to point to the next available node (if avail is NULL, then there are no more available nodes).
struct node *getNewNode( void )
{
struct node *newNode = NULL;
if ( avail ) /* if the available list isn't empty */
{
newNode = avail; /* grab first available node */
avail = avail->next; /* set avail to point to next available node */
newNode->next = NULL; /* sever newNode from available list, */
} /* which we do *after* we update avail */
/* work it out on paper to understand why */
return newNode;
}
When you're done with a node, add it back to the head of the available list:
void freeNode( struct node *n )
{
n->next = avail;
avail = n;
}
We're not using dynamic memory in the sense that we aren't calling mallic or free; however, we've pretty much recapitulated dynamic memory functionality, with the additional limitation that our "heap" has a fixed upper size.
Note that some embedded systems don't have a heap as such, so you'd have to do something like this to implement a list on such systems.
You can write a singly linked list with out malloc , but make sure the implementation is done in main. but what about writing program for traversing , finding least number ,etc . these struct node variables will go out of scope .
struct node{
int a;
struct node* nextNode;
};
int main()
{
struct node head,node1,node2;
head.a=45;
node1.a=98;
node2.a=3;
head.nextNode=&node1;
node1.nextNode=&node2;
node2.nextNode=NULL;
if(head.nextNode== NULL)
{
printf("List is empty");
}
struct node* ptr=&head;
while(ptr!=NULL)
{
printf("%d ",ptr->a);
ptr=ptr->nextNode;
}
}

How to initialize a Linked List with a struct with many variables

I still have troubles with the relations between the linked lists and the structures.
See, my objectif is to create a list where each node contains 2 characters strings. So, I tried something like this : first, I create a structure that represent an element with my 2 char ; second, a control structure for my list, thath will point at the beginning of my list. Which, in my .h, gives something like this :
typedef struct s_def { char *first_word; char *second_word; struct s-def *next; } t_def
typedef struct s_type { t_def *first; } t_list;
Next, I try to initialize my list. I make a function that work like this :
t_list *list;
t_def *words;
list = malloc(sizeof(*list));
words = malloc(sizeof(*words));
if (list == 0 || words == 0)
return (NULL);
words = NULL;
words->next = NULL;
list->first = words;
return (list);
Precision : I try to make an empty list for now, so that the user can add some elements later.
And that's where it block : when I run the program, it gives the typical Segmentation Fault. But it don't see what's wrong with what I made ! I put some write in my function to retrace the process : the malloc are working ok, as well as the words = NULL, but then the segment fault seems to run at the line
words->next = NULL;
What do I make wrong ? Why can't I give a NULL value at the next of my words ?
You first initialize the word pointer with allocated memory
words = malloc(sizeof(*words));
Then 3 lines down you set that pointer to NULL again, creating a memory leak
words = NULL;
And then you try to dereference the pointer that you just set to NULL:
words->next = NULL;
So, just remove the words = NULL;
The problem is most likely this part:
words = NULL;
words->next = NULL;
Here you reassign the pointer words to be a null pointer, and directly afterwards you dereference this null pointer, leading to undefined behavior.
When you set words to NULL, you have made a null pointer. Trying to access it immediately afterwards by words->next is effectively doing NULL->next which will cause an error.
Your code looks a little more complex than it needs to be for a simple linked list implementation, you might try something like:
typedef struct s_element
{
char* firstWord;
char* secondWord;
s_element* next;
} t_element;
t_element* list = NULL;
t_element* addFront(t_element* list, char* word1, char* word2)
{
t_element* next = list;
list = malloc(sizeof(t_element));
if (!list) return NULL;
list->firstWord = word1;
list->secondWord = word2;
list->next = next;
return list;
}
Assuming I haven't made any bone-headed syntax mistakes, this should be about as clear as a linked list can get. Notice that it doesn't need to check if the list is empty, the only conditional is in case malloc has failed.

Linked List in C error -- Invalid Initalizer error

I am attempting to create a Linked List using C (NOT C++). The Linked List is initialized through the function llinit() which should return a list struct. However, when I compile the code I get an error stating "error: invalid initializer" in the lltester.c file. Why is this?
This is the function used to initialize the linked list in my llist.c file:
list llinit()
{
list* ll = malloc(sizeof(list));
ll->head = NULL;
ll->tail = NULL;
return *ll;
}
This is the list struct in my llist.h file:
typedef struct {
node *head;
node *tail;
} list;
This is my main function in my lltester.c file where I attempt to initialize the list:
int main()
{
list myList= llinit(); //This is the line where the error occurs on!
return 0;
}
Your code is leaking memory, since it's allocating the list with malloc() then returning that structure's content by value.
if you want to have a function that returns an empty list by value, you should do just that:
list llinit()
{
list ll;
ll.head = NULL;
ll.tail = NULL;
return ll;
}
The above is just fine, there's no risk of the value "disappearing" due to it going out of scope, this is just as safe as e.g. a function returning a local int value. The return value (all of it!) is copied to the caller's memory as needed.
It's then trivial for the caller to decide whether or not the node should be on the heap or not.
UPDATE: Here is the code on ideone, it really does compile and does not generate an error for the assignment in main().
you have to declare the structure as
typedef struct _list{
list* head; /* could have been struct node* as well */
list* tail;
} list;
Also the list is your custom struture. And the llPushBack() is not a bember of your structure.

unable to access memory 0X.... C program (Ubuntu 12.10)

Purpose of code:
TO maintain a unique element link list...UFID is the keyword for unique
Structure declaration:
struct sharedFiles
{
char UFID[50];
int valid; //valid 1 if someone have this file in write mode
int shared; //no of user's reading this file
struct sharedFiles *next; //pointer to next node
}*sfstart,*sfend; //sfstart points to the first node of linked list and efend to the last node of linked list so that it will be easy to just insert at the end without traversing the linked list
Error Description:
The below code gives segmentation fault when I invoking it 2nd time.
I tried to debug with GDB and it says unable to access the location at line
if(strcmp(sftemp->UFID,ufid)==0)
In the above line it is unable to access sftemp->UFID
/*Function code*/
int addShareList(char *ufid,int mode) //mode=0 (read) and mode=1 (Write request)
{
struct sharedFiles *sftemp,*newnode;
sftemp=sfstart;
if(sfstart==NULL) //if list is empty add first node
{
sfstart=(struct sharedFiles *) malloc(sizeof(struct sharedFiles));
strcpy(sfstart->UFID,ufid);
sfstart->valid=mode;
sfstart->shared=1;
sfstart->next=NULL;
sfend=sfstart; //this node will also be last node of Linked list
return 0;
}
else //if list is not empty
{
while(sftemp->next != NULL) //traverse till last node
{
if(strcmp(sftemp->UFID,ufid)==0)
{
//here if same node found some manupulation to the struct variables
}
sftemp=sftemp->next;
} //while
if(sftemp->next==NULL) //procvess last node
{
if(strcmp(sftemp->UFID,ufid)!=0) //if last node not same add node at the end of Linked list
{
newnode=(struct sharedFiles *) malloc(sizeof(struct sharedFiles));
strcpy(newnode->UFID,ufid);
newnode->valid=mode;
newnode->shared=1;
newnode->next=NULL;
sftemp->next=newnode;
sfend=newnode;
return 0;
}
else //if last node is same
{
//some manipulations to struct variables
}
} //if
}
return -1;
}//addShareList
The above code works fine for inserting first element.When I invoke the same function for inserting second node in the linked list it unable to access the first node while comarision
in the line if(strcmp(sftemp->UFID,ufid)==0). Hope now the purpose of code is clear.
Thanks in advance..
In the while you check if sftemp!=NULL so we can be sure that in the second iteration, after line sftemp=sftemp->next; the pointer contain allocated memory.
But, since I don't know how the list it structured, I can't be sure that the content contains another node of sharedFiles type, it could contain an end-list node which not contains UFID attribute.
So, check in your list how to control if the list is finished.
Another solution can be to change your check this way:
while(sftemp->next!=NULL)
...
if(sftemp->next==NULL) {
//add the node in the right way, consider the end-list node
}
EDIT:
Furthermore, change in the first if the line sftemp->next = NULL; to sfnext->next = NULL;.
And be sure to initialize stnext = NULL.
EDIT 2:
Now that you post struct declaration I still cannot see when you initialize sfstart. Try to do this:
Structure declaration:
struct sharedFiles
{
char UFID[50];
int valid; //valid 1 if someone have this file in write mode
int shared; //no of user's reading this file
struct sharedFiles *next; //pointer to next node
}*sfstart = NULL,*sfend;
Normally the answer for this is that the pointer is NULL, which in your case means malloc has failed because you're out of memory - you really should be checking the return value.
The most likely cause for your problem is that you have corrupted the heap, so that sftemp no longer points to a valid memory address. Check what it's value is that might give you some more clues.

Resources