开发者

Glib type testing macros cause segfault when passed a GSList

开发者 https://www.devze.com 2023-03-02 05:31 出处:网络
Passing a GSList to a Glib macro (Like G_OBJECT_TYPE_NAME(), GTK_IS_WIDGET() etc) causes a segmentation fault.

Passing a GSList to a Glib macro (Like G_OBJECT_TYPE_NAME(), GTK_IS_WIDGET() etc) causes a segmentation fault.

This is a problem as my program has to process a list of GObjects and can't test for GSLists... In addition, merely performing a test on a GSList causes a segfault so it can't even get to an else block.

Does anyone know why this is happening?

#include <gtk/gtk.h>
int main (int argc, char *argv[])
{
    g_type_init();
    GtkWidget * widget;

    GSList * gslist = NULL;
    gslist = g_slist_append(gslist,widget);

    GHashTable * table = g_hash_table_new(NULL,NULL);
    g_hash_table_insert(table, (gchar *) "key", (char *) "value");
    g_hash_table_insert(table, (gchar *) "slist", gslist);

    if(GTK_IS_WIDGET(g_hash_table_lookup(table,"slist"))){}
} 

Segfault occu开发者_StackOverflow社区rs in g_type_check_instance_is_a () from /usr/lib/libgobject-2.0.so.0, removing GTK_IS_WIDGET program runs fine.


A GSListis not a GObject i.e. it does not provide the machinery necessary for the type-check macros to work, which results in the crash you observe. If you really need such functionality, you might need to create a wrapper (based on GObject) for your lists.

Unfortunately, you cannot test for the type of value in your hash table; the type-checking macros used by GObject and GTK actually require a dedicated support in the value being pointed to, i.e., you have to positively know, that the value is something, which uses the GObject machinery before you can use the macros in the first place. The results are simply undefined, if they are applied to pointers to anything but GObject-derived types, and more often than not will cause crashes.

Note, BTW., that this problem arises with the string values (char*) and other values as well. (Why do you cast "value" to char*?)

If you really need to work with a generic hash table like stated in your example, you will have to create a wrapper of some kind; either directly derive it from GObject or try something minimal like

typedef struct {
     int type_code;
     union {
         int ival;
         char* str;
         GObject* obj;
         GSList* list;
     } value;
} Cell;

typedef enum {
     INTEGER, STRING, OBJECT, LIST
} CellType;

Cell* 
allocate_int_cell(int value)
{
    ...
} 

Things are unfortunately even more complicated than this, because you will also have to manage the destruction of your values when they are removed from the hash table (or if the hash table itself is destroyed).


What you're basically doing is:

if (GTK_IS_WIDGET(gslist))

As Dirk already said, this won't work as GSList is not a GObject. This is the data inside the GList that you should check, not the GSList itself.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号