I am building a C programm for University project. It uses SQLITE3 for database and GTK3 for graphic user interface. I use GtkComboBoxText (dropdown menu) widget and gtk_combo_box_text_append()
and gtk_combo_box_text_remove()
functions to add and remove rows from GtkComboBoxText.
When programm gets to gtk_combo_box_text_remove()
it crashes but only on Linux, when i run it on Windows it works perfectly. This function takes only a pointer to GtkComboBoxText and an integer which is index of the row that gets removed.
When I run the Valgrind to detect where the memory error is I get this. Is it my mistake or Gtk bug?
==30432== Invalid read of size 1
==30432== at 0x7D08730: __strcpy_sse2_unaligned (in /lib64/libc-2.26.so)
==30432== by 0x405A70: on_combo_changed (main.c:981)
==30432== by 0x72D7E95: ??? (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x72F447B: g_signal_emit_valist (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x72F49CE: g_signal_emit (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x52DAF1B: ??? (in /usr/lib64/libgtk-3.so.0.2404.16)
==30432== by 0x72D7C5C: g_closure_invoke (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x72EB84D: ??? (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x72F404B: g_signal_emit_valist (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x72F49CE: g_signal_emit (in /usr/lib64/libgobject-2.0.so.0.6200.6)
==30432== by 0x53B0758: gtk_list_store_remove (in /usr/lib64/libgtk-3.so.0.2404.16)
==30432== by 0x52DEEB8: gtk_combo_box_text_remove (in /usr/lib64/libgtk-3.so.0.2404.16)
==30432== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==30432==
==30432==
==30432== Process terminating with default action of signal 11 (SIGSEGV): dumping core
I tried to allocate more stack size but it didn't work. I played around with a few more different things but they didn't seem to work.
EDIT:
I recreated this problem with a small code. Valgrind shows the same thing and like before it runs on Windows but not on Linux.
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
GtkBuilder *builder;
GtkWidget *window;
GtkWidget *fixed;
GtkWidget *button;
GtkWidget *label;
GtkComboBoxText *combo;
char active[100];
int foo = 0;
int main(int argc, char *argv[]){
gtk_init(&argc, &argv);
builder = gtk_builder_new_from_file("test.glade");
window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
fixed = GTK_WIDGET(gtk_builder_get_object(builder, "fixed"));
combo = GTK_COMBO_BOX_TEXT(gtk_builder_get_object(builder, "combo"));
button = GTK_WIDGET(gtk_builder_get_object(builder, "button"));
label = GTK_WIDGET(gtk_builder_get_object(builder, "label"));
gtk_builder_connect_signals(builder, NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "something");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "something 2");
gtk_widget_show_all(window);
gtk_main();
return EXIT_SUCCESS;
}
void on_button_clicked () {
gtk_combo_box_text_remove(combo, foo);
}
void on_combo_changed () {
sprintf(active, "%s", gtk_combo_box_text_get_active_text(combo));
foo = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
}
I used this glade file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="window">
<property name="width-request">400</property>
<property name="height-request">200</property>
<property name="can-focus">False</property>
<property name="default-width">400</property>
<property name="default-height">200</property>
<child>
<!-- n-columns=1 n-rows=3 -->
<object class="GtkGrid" id="grid">
<property name="width-request">400</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkButton" id="button">
<property name="label" translatable="yes">button</property>
<property name="width-request">400</property>
<property name="height-request">60</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_button_clicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="width-request">400</property>
<property name="height-request">60</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">example</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="combo">
<property name="width-request">400</property>
<property name="height-request">80</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="changed" handler="on_combo_changed" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Compiled with :
gcc -g -Wall -Wextra -o main main.c `pkg-config --cflags --libs gtk+-3.0 gmodule-2.0`
dimich is right saying
After deletion no active string is selected,
gtk_combo_box_text_get_active_text()
returns NULL. Maybe your implementation doesn't allow NULL as argument for"%s"
insprintf()
.
- the problem is that gcc
optimizes sprintf(active, "%s", …)
to strcpy(active, …)
, and it's no surprise that strcpy
crashes with a NULL source. So just handle that somehow, e. g.:
sprintf(active, "%s", gtk_combo_box_text_get_active_text(combo) ?: "");