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

发布于 2024-11-05 00:49:08 字数 802 浏览 1 评论 0原文

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

这是一个问题,因为我的程序必须处理 GObject 列表,并且无法测试 GSLists...此外,仅对 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"))){}
} 

/usr/lib/libgobject-2.0.so.0 中的 g_type_check_instance_is_a () 中出现段错误,删除 GTK_IS_WIDGET 程序运行正常。

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 occurs in g_type_check_instance_is_a () from /usr/lib/libgobject-2.0.so.0, removing GTK_IS_WIDGET program runs fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

命比纸薄 2024-11-12 00:49:09

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)
{
    ...
} 

不幸的是事情比这更复杂,因为当你的值从哈希表中删除时(或者如果哈希表本身被破坏)。

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).

纸短情长 2024-11-12 00:49:09

你基本上要做的是:

if (GTK_IS_WIDGET(gslist))

正如 Dirk 已经说过的,这不会起作用,因为 GSList 不是 GObject。这是您应该检查的 GList 内部的数据,而不是 GSList 本身。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文