Search code examples
csqlitegtkvalgrindgtk3

GTK 3 programm works on Windows but crashes on Linux


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`

Solution

  • 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" in sprintf().

    - 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) ?: "");