Макросы тестирования типа Glib вызывают segfault при передаче GSList - PullRequest
0 голосов
/ 03 мая 2011

Передача GSList в макрос Glib (например, G_OBJECT_TYPE_NAME(), GTK_IS_WIDGET() и т. Д.) Вызывает ошибку сегментации.

Это проблема, поскольку моя программа должна обработать список объектов GObject и можеттест для списков GSList ... Кроме того, простое выполнение теста для GSList вызывает segfault, поэтому он не может даже попасть в блок 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"))){}
} 

Segfault происходит в g_type_check_instance_is_a () from /usr/lib/libgobject-2.0.so.0, удаление программы GTK_IS_WIDGET выполняется нормально.

Ответы [ 2 ]

1 голос
/ 04 мая 2011

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

К сожалению, все еще сложнее, потому что вам также придется управлять уничтожением ваших значений, когда они удаляются из хешатаблица (или если сама хеш-таблица уничтожена).

0 голосов
/ 04 мая 2011

Что вы в основном делаете:

if (GTK_IS_WIDGET(gslist))

Как уже сказал Дирк, это не сработает, поскольку GSList не является GObject.Это данные внутри GList, которые вы должны проверить, а не сам GSList.

...