将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程序运行正常。
答案 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本身。