www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Varargs issue with LDC

reply Don Allen <donaldcallen gmail.com> writes:
As mentioned in previous posts, I've written a personal finance 
manager in D (ported from the original C) that works well when 
compiled with dmd.

When compiled with ldc, however, it segfaults when I try to 
perform an operation that involves a call to a varargs function 
in gtk3. The segfault occurs in the
bowels of gtk3, but a backtrace in gdb shows that the last thing 
that happened in my code was the call to the varargs function 
that I refer to above. At this point I am assuming, but do not 
know, that the issue is related to the varargs nature of the 
called gtk function.

This is disappointing. Has anyone experienced a similar issue 
with ldc or knows of known varargs problems with ldc? I did check 
the ldc github repository and did not find an open issue that 
sounds similar to what I'm seeing.

This problem occurred on an up-to-date Arch Linux system with the 
latest release of ldc installed.

/Don Allen
Jan 31
next sibling parent reply Hipreme <msnmancini hotmail.com> writes:
On Wednesday, 31 January 2024 at 15:25:44 UTC, Don Allen wrote:
 As mentioned in previous posts, I've written a personal finance 
 manager in D (ported from the original C) that works well when 
 compiled with dmd.

 When compiled with ldc, however, it segfaults when I try to 
 perform an operation that involves a call to a varargs function 
 in gtk3. The segfault occurs in the
 bowels of gtk3, but a backtrace in gdb shows that the last 
 thing that happened in my code was the call to the varargs 
 function that I refer to above. At this point I am assuming, 
 but do not know, that the issue is related to the varargs 
 nature of the called gtk function.

 This is disappointing. Has anyone experienced a similar issue 
 with ldc or knows of known varargs problems with ldc? I did 
 check the ldc github repository and did not find an open issue 
 that sounds similar to what I'm seeing.

 This problem occurred on an up-to-date Arch Linux system with 
 the latest release of ldc installed.

 /Don Allen
Works well in DMD, crashes on LDC, arguments issue. Take a look if you're using the correct `extern(C)` and `extern(D)` in the right places. Depending on the compiler you're using, `extern` does more than name mangling, it also changes the order in which the argument are received. Also, on a related note: I don't know if you're doing it or not, but always mark vararg as `scope`. That means you can't save them anywhere, why? Because you really can't. varargs are stack allocated so it may also cause a segfault if you try to access them after the function exits its scope. Also, you should post this on Learn instead.
Jan 31
parent reply Don Allen <donaldcallen gmail.com> writes:
On Wednesday, 31 January 2024 at 16:19:17 UTC, Hipreme wrote:
 On Wednesday, 31 January 2024 at 15:25:44 UTC, Don Allen wrote:
 As mentioned in previous posts, I've written a personal 
 finance manager in D (ported from the original C) that works 
 well when compiled with dmd.

 When compiled with ldc, however, it segfaults when I try to 
 perform an operation that involves a call to a varargs 
 function in gtk3. The segfault occurs in the
 bowels of gtk3, but a backtrace in gdb shows that the last 
 thing that happened in my code was the call to the varargs 
 function that I refer to above. At this point I am assuming, 
 but do not know, that the issue is related to the varargs 
 nature of the called gtk function.

 This is disappointing. Has anyone experienced a similar issue 
 with ldc or knows of known varargs problems with ldc? I did 
 check the ldc github repository and did not find an open issue 
 that sounds similar to what I'm seeing.

 This problem occurred on an up-to-date Arch Linux system with 
 the latest release of ldc installed.

 /Don Allen
Works well in DMD, crashes on LDC, arguments issue. Take a look if you're using the correct `extern(C)` and `extern(D)` in the right places. Depending on the compiler you're using, `extern` does more than name mangling, it also changes the order in which the argument are received.
The called gtk function has this prototype, which I believe is correct: ```` extern (C) GtkListStore* gtk_list_store_new (gint n_columns, ...); ```` The call site looks like ```` writefln("debug: %d", NMktStore.num_cols); store = gtk_list_store_new(NMktStore.num_cols, g_type_string, // date g_type_string, // num g_type_string, // description g_type_boolean, // r g_type_string, // transaction guid g_type_string, // value g_type_string); // balance ```` The debugging writefln prints "debug: 7", which is correct.
 Also, on a related note: I don't know if you're doing it or 
 not, but always mark vararg as `scope`. That means you can't 
 save them anywhere, why? Because you really can't. varargs are 
 stack allocated so it may also cause a segfault if you try to 
 access them after the function exits its scope.
I'm not sure what you mean here. Maybe you can be more explicit after seeing the extern and call above.
 Also, you should post this on Learn instead.
I thought of that, but wanted a wider audience for my question.
Jan 31
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Wednesday, 31 January 2024 at 17:16:51 UTC, Don Allen wrote:

 The called gtk function has this prototype, which I believe is 
 correct:
 ````
 extern (C) GtkListStore* gtk_list_store_new (gint n_columns, 
 ...);
 ````
Here is what gtkd defines: https://github.com/gtkd-developers/GtkD/blob/17d7dc25e1adc9b86aff381b950f21706118ebeb/generated/gtkd/gtk/c/functions.d#L7467
 The call site looks like
 ````
         writefln("debug: %d",  NMktStore.num_cols);
         store = gtk_list_store_new(NMktStore.num_cols,
                 g_type_string, // date
                 g_type_string, // num
                 g_type_string, // description
                 g_type_boolean, // r
                 g_type_string, // transaction guid
                 g_type_string, // value
                 g_type_string); // balance
 ````
 The debugging writefln prints "debug: 7", which is correct.
I'm assuming gint is int? Did you validate that the type constants are correct? Double check against gtkd. It doesn't seem to be anything with this call on first glance. -Steve
Jan 31
parent Don Allen <donaldcallen gmail.com> writes:
On Wednesday, 31 January 2024 at 17:54:56 UTC, Steven 
Schveighoffer wrote:
 On Wednesday, 31 January 2024 at 17:16:51 UTC, Don Allen wrote:

 The called gtk function has this prototype, which I believe is 
 correct:
 ````
 extern (C) GtkListStore* gtk_list_store_new (gint n_columns, 
 ...);
 ````
Here is what gtkd defines: https://github.com/gtkd-developers/GtkD/blob/17d7dc25e1adc9b86aff381b950f21706118ebeb/generated/gtkd/gtk/c/functions.d#L7467
 The call site looks like
 ````
         writefln("debug: %d",  NMktStore.num_cols);
         store = gtk_list_store_new(NMktStore.num_cols,
                 g_type_string, // date
                 g_type_string, // num
                 g_type_string, // description
                 g_type_boolean, // r
                 g_type_string, // transaction guid
                 g_type_string, // value
                 g_type_string); // balance
 ````
 The debugging writefln prints "debug: 7", which is correct.
I'm assuming gint is int?
typedef int gint; Did you validate that the type
 constants are correct? Double check against gtkd.
Yes, they are correct. I wrote a little C program that generates an importable D file with various gtk constant definitions obtained from the gtk header files. Yes, it's a pre-ImportC kludge. And yes, I checked that the result of the kludge agrees with the original gtk.h definitions. And if they weren't correct, I'm very sure the dmd version wouldn't work nearly as well as it does :-)
 It doesn't seem to be anything with this call on first glance.

 -Steve
Jan 31
prev sibling parent reply Johan <j j.nl> writes:
On Wednesday, 31 January 2024 at 17:16:51 UTC, Don Allen wrote:
 The called gtk function has this prototype, which I believe is 
 correct:
 ````
 extern (C) GtkListStore* gtk_list_store_new (gint n_columns, 
 ...);
 ````
 The call site looks like
 ````
         writefln("debug: %d",  NMktStore.num_cols);
         store = gtk_list_store_new(NMktStore.num_cols,
                 g_type_string, // date
                 g_type_string, // num
                 g_type_string, // description
                 g_type_boolean, // r
                 g_type_string, // transaction guid
                 g_type_string, // value
                 g_type_string); // balance
 ````
Did you check that the D type of `g_type_string/boolean` matches the size of the type of the C constants? (`GType` which is `unsigned long` in C, https://codebrowser.dev/gtk/gtk/subprojects/glib/gobject/gtype.h.html#383) -Johan
Jan 31
next sibling parent Johan <j j.nl> writes:
On Wednesday, 31 January 2024 at 18:11:43 UTC, Johan wrote:
 On Wednesday, 31 January 2024 at 17:16:51 UTC, Don Allen wrote:
 The called gtk function has this prototype, which I believe is 
 correct:
 ````
 extern (C) GtkListStore* gtk_list_store_new (gint n_columns, 
 ...);
 ````
 The call site looks like
 ````
         writefln("debug: %d",  NMktStore.num_cols);
         store = gtk_list_store_new(NMktStore.num_cols,
                 g_type_string, // date
                 g_type_string, // num
                 g_type_string, // description
                 g_type_boolean, // r
                 g_type_string, // transaction guid
                 g_type_string, // value
                 g_type_string); // balance
 ````
Did you check that the D type of `g_type_string/boolean` matches the size of the type of the C constants? (`GType` which is `unsigned long` in C, https://codebrowser.dev/gtk/gtk/subprojects/glib/gobject/gtype.h.html#383) -Johan
Here is a small example in godbolt. LDC and Clang generate identical assembly code, so looks like LDC is doing the right thing here. https://d.godbolt.org/z/rMK1PqKjv What C/C++ (nota bene) compiler did you use to build Gtk ? -Johan
Jan 31
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Wednesday, 31 January 2024 at 18:11:43 UTC, Johan wrote:
 Did you check that the D type of `g_type_string/boolean` 
 matches the size of the type of the C constants? (`GType` which 
 is `unsigned long` in C, 
 https://codebrowser.dev/gtk/gtk/subprojects/glib/gobject/gtype.h.html#383)
gtkd project uses `size_t` https://github.com/gtkd-developers/GtkD/blob/17d7dc25e1adc9b86aff381b950f21706118ebeb/generated/gtkd/gobject/c/types.d#L51 -Steve
Jan 31
parent Don Allen <donaldcallen gmail.com> writes:
On Wednesday, 31 January 2024 at 20:01:51 UTC, Steven 
Schveighoffer wrote:
 On Wednesday, 31 January 2024 at 18:11:43 UTC, Johan wrote:
 Did you check that the D type of `g_type_string/boolean` 
 matches the size of the type of the C constants? (`GType` 
 which is `unsigned long` in C, 
 https://codebrowser.dev/gtk/gtk/subprojects/glib/gobject/gtype.h.html#383)
gtkd project uses `size_t` https://github.com/gtkd-developers/GtkD/blob/17d7dc25e1adc9b86aff381b950f21706118ebeb/generated/gtkd/gobject/c/types.d#L51 -Steve
The D type of g_type_xxxxx was the answer. My hack had defined it as uint, should be ulong. So the arguments on the stack were not what the C code was expecting. Now I wonder why my code worked with dmd. My most cpu-intensive application, the report generator, is about 9% faster compiled with ldc than dmd, both in release mode. Thanks to everyone who replied and especially Johan, who asked the question that led me to the answer.
Jan 31
prev sibling next sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Wednesday, 31 January 2024 at 15:25:44 UTC, Don Allen wrote:
 As mentioned in previous posts, I've written a personal finance 
 manager in D (ported from the original C) that works well when 
 compiled with dmd.

 When compiled with ldc, however, it segfaults when I try to 
 perform an operation that involves a call to a varargs function 
 in gtk3. The segfault occurs in the
 bowels of gtk3, but a backtrace in gdb shows that the last 
 thing that happened in my code was the call to the varargs 
 function that I refer to above. At this point I am assuming, 
 but do not know, that the issue is related to the varargs 
 nature of the called gtk function.

 This is disappointing. Has anyone experienced a similar issue 
 with ldc or knows of known varargs problems with ldc? I did 
 check the ldc github repository and did not find an open issue 
 that sounds similar to what I'm seeing.

 This problem occurred on an up-to-date Arch Linux system with 
 the latest release of ldc installed.

 /Don Allen
If you can create a minimal project that reproduces the issue, it'll help people hunt for the bug
Jan 31
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Wednesday, 31 January 2024 at 15:25:44 UTC, Don Allen wrote:
 As mentioned in previous posts, I've written a personal finance 
 manager in D (ported from the original C) that works well when 
 compiled with dmd.

 When compiled with ldc, however, it segfaults when I try to 
 perform an operation that involves a call to a varargs function 
 in gtk3. The segfault occurs in the
 bowels of gtk3, but a backtrace in gdb shows that the last 
 thing that happened in my code was the call to the varargs 
 function that I refer to above. At this point I am assuming, 
 but do not know, that the issue is related to the varargs 
 nature of the called gtk function.

 This is disappointing. Has anyone experienced a similar issue 
 with ldc or knows of known varargs problems with ldc? I did 
 check the ldc github repository and did not find an open issue 
 that sounds similar to what I'm seeing.

 This problem occurred on an up-to-date Arch Linux system with 
 the latest release of ldc installed.
It could be an ABI problem. varargs are weird. What is the function? Is it possible to make a small example that uses gtk3 and still reproduces the issue? Are you defining the prototype yourself, or using a binding? -Steve
Jan 31
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On Wednesday, 31 January 2024 at 17:36:26 UTC, Steven 
Schveighoffer wrote:
 What is the function? Is it possible to make a small example 
 that uses gtk3 and still reproduces the issue? Are you defining 
 the prototype yourself, or using a binding?
Oh, I see you responded with this info elsewhere. -Steve
Jan 31