将GSList
传递给Glib宏(例如G_OBJECT_TYPE_NAME()
,GTK_IS_WIDGET()
等)会导致分段错误。
这是一个问题,因为我的程序必须处理GObjects列表,并且无法测试GSList...。此外,仅对GSList执行测试会导致段错误,因此它甚至无法到达else块。
有人知道为什么会这样吗?
#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"))){}
}
段错误发生在
g_type_check_instance_is_a () from /usr/lib/libgobject-2.0.so.0
中,删除GTK_IS_WIDGET程序运行正常。 最佳答案
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)
{
...
}
不幸的是,事情要比这复杂得多,因为当从哈希表中删除值(或者哈希表本身已被破坏)时,您还必须管理值的破坏。