After adding 10 structures to a GSList, using g_slist_last
to retrieve the last structure does not produce the same result as using g_slist_foreach
to view the last structure.
Code sample:
#include <glib-2.0/glib.h>
/* Compile command
gcc main.c -lglib-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
*/
typedef struct {
int a;
int b;
} MyStruct;
void print_data(gpointer data, gpointer user_data) {
MyStruct *my_struct = (MyStruct *)data;
g_print("a: %d, b: %d\n",my_struct->a, my_struct->b);
}
int main(int argc, char *argv[]) {
GSList *list = NULL;
/* Instantiate 10 structures and add them to the GSList */
for (int i=0; i<10; i++) {
MyStruct *my_struct = (MyStruct *)g_malloc(sizeof(MyStruct));
my_struct->a = i;
my_struct->b = i;
list = g_slist_append ( list, my_struct);
}
/* Get the last structure in the list; print the values */
MyStruct *my_struct = (MyStruct *)g_slist_last (list);
g_print("a: %d, b: %d\n",my_struct->a, my_struct->b);
/* Iterate over each structure in the list; print the values */
g_slist_foreach (list, print_data, NULL);
return 0;
}
Output:
a: -554252672, b: 21853 <- result of g_slist_last, which is garbage
a: 0, b: 0
a: 1, b: 1
a: 2, b: 2
a: 3, b: 3
a: 4, b: 4
a: 5, b: 5
a: 6, b: 6
a: 7, b: 7
a: 8, b: 8
a: 9, b: 9 <- last structure in the list which is correct
In this sample, why does g_slist_last
give a result different from the last structure using g_slist_foreach
?
A GSList
structure contains two elements: the next
pointer and the data
pointer. The latter points to the elements you appended to the list.
The g_slist_last()
returns a pointer to the last GSList
structure, not the element you appended. Therefore the cast to MyStuct *
is wrong.
Correct code:
GSList *last = g_slist_last(list);
MyStruct *last_data = last->data;
g_print("a: %d, b: %d\n", last_data->a, last_data->b);
With that change, the output becomes:
a: 9, b: 9
a: 0, b: 0
a: 1, b: 1
...
a: 8, b: 8
a: 9, b: 9
P.S. To understand this, it might be helpful to use a debugger (or change the code) to print the values of list
, my_struct
, last
and last_data
:
0: list=0x1be2470 my_struct=0x1be2450
1: list=0x1be2470 my_struct=0x1be2790
...
8: list=0x1be2470 my_struct=0x1be2ec0
9: list=0x1be2470 my_struct=0x1be2f00
list=0x1be2470 last=0x1be2ee0 last_data=0x1be2f00
Note that on the first iteration list != my_struct
even though the list
only contains one element, and the last
is not the same as last_data
.