I'm using in my C project list_head structure to define a linked_list. In some conditions I need to parse the list from the second element, but in this case I get an additional element with a garbage value. I tried with a small program in my pc to simulate the same scenario. I get the same issue:
#include<stdio.h>
#include<stdlib.h>
#include "list.h"
struct struct_report{
struct list_head list;
char *report;
};
//Add an element to the linked list
void add_report_to_list(struct list_head *reports, char *report) {
struct struct_report *report_strct;
report_strct = calloc(1, sizeof(struct struct_report));
list_add_tail(&report_strct->list, reports);
report_strct->report= strdup(report);
}
int main() {
struct struct_report *retreport;
LIST_HEAD(reports); //instantiate a struct list_head instance
add_report_to_list(&reports, "elt1");
add_report_to_list(&reports, "elt2");
add_report_to_list(&reports, "elt3");
add_report_to_list(&reports, "elt4");
list_for_each_entry(retreport, &reports, list){
printf("============> no next retreport: %s\n", retreport->report);
}
printf("\n");
list_for_each_entry(retreport, reports.next, list){
printf("============> Next retreport: %s\n", retreport->report);
}
return 1;
}
list.h is the same of linux: https://github.com/torvalds/linux/blob/master/include/linux/list.h
I get as an execution result the following trace:
============> no next retreport: elt1
============> no next retreport: elt2
============> no next retreport: elt3
============> no next retreport: elt4
============> Next retreport: elt2
============> Next retreport: elt3
============> Next retreport: elt4
============> Next retreport:
It's clear that in the case I start parsing normally from the first element I don't have any problem. But in the case I start from the second element in the list I get an additional one with strange value like garbage.
Has some an explanation why I get an additional element? And how I can fix it to parse until elt4?
If you start from the first element of the list (and not from the head) then the list_for_each_entry()
will stop in the same list object because it's a circular list.
So the list_for_each_entry()
will go through the head. And the head is not attached to an entry. so when you try to refer to the entry from the head list then you will get garbage
Solution: start the loop from the head of the list and skip the first element