传递GSList时,Glib类型测试宏会导致段错误

时间:2011-05-03 18:09:32

标签: c gtk segmentation-fault glib

GSList传递给Glib宏(如G_OBJECT_TYPE_NAME()GTK_IS_WIDGET()等)会导致分段错误。

这是一个问题,因为我的程序必须处理GObject列表而不能测试GSLists ...此外,仅仅对GSList执行测试会导致段错误,因此它甚至无法访问其他地方块。

有谁知道为什么会这样?

#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发生在g_type_check_instance_is_a () from /usr/lib/libgobject-2.0.so.0,删除GTK_IS_WIDGET程序运行正常。

2 个答案:

答案 0 :(得分:1)

GSList不是GObject,即它不提供类型检查宏工作所需的机制,这会导致您观察到崩溃。如果您确实需要此类功能,则可能需要为列表创建一个包装器(基于GObject)。

不幸的是,您无法测试哈希表中的值类型; GObject和GTK使用的类型检查宏实际上需要在指向的值中提供专用支持,即,您必须肯定地知道值是某种东西,它之前使用GObject机制你可以在第一时间使用宏。如果将结果应用于除GObject派生类型以外的任何指针,则结果只是未定义,并且通常会导致崩溃。

注意,顺便说一句,这个问题出现在字符串值(char*)和其他值上。 (为什么要将"value"投射到char*?)

如果您确实需要使用如示例中所述的通用哈希表,则必须创建某种包装器;要么直接从GObject派生,要么尝试像

这样的最小值
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)
{
    ...
} 

遗憾的是,事情比这更复杂,因为当你从哈希表中删除它们时(或者如果哈希表本身被破坏),你还必须管理你的值的破坏。

答案 1 :(得分:0)

你基本上做的是:

if (GTK_IS_WIDGET(gslist))

正如Dirk已经说过的那样,这不会起作用,因为GSList不是GObject。这是你应该检查的GList里面的数据 ,而不是GSList本身。