I got a warning and a segmentation fault when compiling and running roughly the following code, which uses the to_utf32_fast
method on a string
and should return the number of UTF-32 characters encoded in the codepoint_count
variable. This method transpiles to the C function g_utf8_to_ucs4_fast
and somehow out codepoint_count
ends up as long * *
argument instead of the expected long *
.
I do have a workaround, so this isn't urgent.
int main (string[] args) {
string test = "abc";
long codepoint_count;
string utf32_version = test.to_utf32_fast(-1, out codepoint_count).to_string();
stdout.printf("success");
return 0;
}
The relevant part of the output:
C:/msys64/usr/src/outerror.vala.c: In function '_vala_main':
C:/msys64/usr/src/outerror.vala.c:78:50: warning: passing argument 3 of 'g_utf8_to_ucs4_fast' from incompatible pointer type [-Wincompatible-pointer-types]
_tmp2_ = g_utf8_to_ucs4_fast (test, (glong) -1, &_tmp1_);
^
In file included from C:/msys64/mingw64/include/glib-2.0/glib/gstring.h:33:0,
from C:/msys64/mingw64/include/glib-2.0/glib/giochannel.h:34,
from C:/msys64/mingw64/include/glib-2.0/glib.h:54,
from C:/msys64/usr/src/outerror.vala.c:5:
C:/msys64/mingw64/include/glib-2.0/glib/gunicode.h:798:12: note: expected 'glong * {aka long int *}' but argument is of type 'glong ** {aka long int **}'
gunichar * g_utf8_to_ucs4_fast (const gchar *str,
^~~~~~~~~~~~~~~~~~~
I looked at the transpiled C source code and the third argument to g_utf8_to_ucs4_fast
is the address of an uninitialized pointer to long which is later freed with g_free
. This triggers a segfault when the program is run.
Am I doing something wrong in the way I'm calling this function? It's declared as public string32 to_utf32_fast (long len = -1, out long? items_written = null)
.
I'm new to Vala (more familiar with C) and not sure I grasp the argument annotations. The second argument shouldn't be transpiled to C as long **
rather than long *
, but maybe the nullability marker ?
or the default value = null
leads Vala to think that the variable items_written
is a pointer to long
(or the Vala equivalent thereof) rather than long
. If so, then maybe there is an error in the declaration of the method or an ambiguity in Vala syntax.
The declaration is wrong. This code works just fine:
[CCode (cname = "g_utf8_to_ucs4_fast")]
public extern string32 to_utf32_fast_ (string s, long len = -1,
out long items_written);
int main (string[] args) {
string test = "abc";
long codepoint_count;
string32 utf32_version = to_utf32_fast_(test, -1, out codepoint_count);
stdout.printf("success");
return 0;
}
In the original declaration from glib-2.0.vapi the items_written parameter would be a glong**
in C, but it actually is a glong*
.
I have reported this as a bug: