2015-02-18 2 views
0

Я пытаюсь узнать, используя недействительные указатели в C. Вот код, который я написал, используя GLib:gpointer cast to gint * вызывает ошибку сегментации - почему?

#include <stdio.h> 
#include <gtk/gtk.h> 

int 
main (void) 
{ 
    GList *l = NULL; 
    l = g_list_append (l, GINT_TO_POINTER (1)); 
    l = g_list_append (l, GINT_TO_POINTER (2)); 
    l = g_list_append (l, GINT_TO_POINTER (3)); 
    GList *l1 = g_list_nth (l, 1); 
    gpointer snd_element = (l1->data); 
    gint *digit = snd_element; 
    gint forty_two = 40; 
    forty_two = forty_two + *digit; 
    printf ("%d\n", forty_two); 

    return 0; 
} 

поведение я ожидаю от этой программы будет печатать 42. К сожалению, работает он вызывает ошибку сегментации , Зачем?

+0

Почему бы вам не проверить 'l1' и' digit' для NULL перед их использованием? –

+0

Потому что я уверен, что 'g_list_append' фактически добавит некоторые данные в l. Это означает, что l1 должен быть GList *, содержащим 2. – qiubit

ответ

2

g_list_append ожидает указатель на данные, которые вы хотите сохранить для передачи. GINT_TO_POINTER просто преобразует заданное целое число в указатель (т. Е. Это в основном (gpointer)x), поэтому указатель фактически не указывает на какие-либо действительные данные, это всего лишь число. После добавления данных в список, указатели будут иметь значение 1, 2 и 3.

Если предположить, что g_list_nth успешна, l1->data будет указатель передается g_list_append ранее. В этом случае значение указателя будет равно 2 (не значение, на которое указывает значение). Затем вы пытаетесь разыменовать этот указатель, что вызовет ошибку сегментации.

Вместо этого просто верните его обратно на int и не делайте разницы, чтобы вернуть значение. Вы, вероятно, должны использовать предоставленный обратный макрос GPOINTER_TO_INT, хотя, например.

gpointer snd_element = (l1->data); 
gint digit = GPOINTER_TO_INT(snd_element); // Note I've removed the *... 
gint forty_two = 40; 
forty_two = forty_two + digit; // Note I've not attempted to dereference it 
2

Это:

gpointer snd_element = (l1->data); 

Делает snd_element содержать значение 2 но преобразуется в указатель. Это, вероятно, не действительный адрес памяти для вашего процесса.

Так что это:

forty_two = forty_two + *digit; 

которые де-ссылка digit вызывает неопределенное поведение.

Вы должны сделать:

const int forty_two = 40 + GPOINTER_TO_INT(digit); 
+0

«почему вы ожидаете, что 40 + 1 будет 42?» -> 'g_list_nth' принимает индекс на основе нуля;) – slugonamission

Смежные вопросы