String arrays and strv in Vala

I’m using a Gee.ArrayList in Vala to store a set of strings, and want to put them into a GSettings as entry. I’m using

var myGeeArraylist = new Gee.ArrayList<string>();
var mysettings = new GLib.Settings("blah blah");
...
mysettings.set_strv("key", myGeeArraylist.to_array());

The odd thing is that it works, but Valgrind shows a memory access error:

==14571== Invalid read of size 8
==14571==    at 0x5681953: g_strv_length (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8200.1)
==14571==    by 0x56A5FA7: g_variant_new_strv (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8200.1)
==14571==    by 0x54BBD24: g_settings_set_strv (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.8200.1)
==14571==    by 0x138001: __lambda18_ (cronopete.vala:92)
==14571==    by 0x1380E0: ___lambda18__cronopete_c_main_menu_do_ignore_warnings (cronopete.vala:90)

In fact, I discovered this because in a different computer the program crashed. But after using valgrind, both computers show the same error, but only one crashed.

Is it something that I’m doing incorrectly, or is it a bug in Vala?

GStrv (the type g_settings_set_strv() expects) is an array of strings, with a trailing null element (which serves as a delimiter to locate the array’s end – g_settings_set_strv() doesn’t take a length parameter). In practice it’s merely a C char** with the last element being NULL.

Gee.ArrayList.to_array() doesn’t add that trailing null so there’s no guarantee for a null trailing member. In practice, it seems one is often added because the array is grown in blocks which are 0ed out, but for some sizes it isn’t (e.g. add 5 items and there are no extra internal items left), and that’s not a guarantee anyway – but might explain why you don’t see the issue everywhere.

A solution for your use case could be to make the array list hold a nullable string, and explicitly add the trailing null:

var myGeeArraylist = new Gee.ArrayList<string?>();
var mysettings = new GLib.Settings("blah blah");
// ...
myGeeArraylist.add("foo");
myGeeArraylist.add("bar");
myGeeArraylist.add(null); // explicitly add a null member at the end
// ...
mysettings.set_strv("key", myGeeArraylist.to_array());

Whether this is a bug in Vala or just a you need to know this kind of situation I don’t know :slight_smile:

1 Like