Передача массива в функцию - Различные значения - Segfault - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть следующий код:

gpointer w[3];
GtkWidget *menu_item = gtk_menu_item_new();
w[0] = menu_item;
menu_item = gtk_menu_item_new();
w[1] = menu_item;
GtkTextBuffer *buffer = gtk_text_buffer_new(NULL);
w[2] = buffer;

Это все хорошо до сих пор. Давайте теперь подключим сигнал:

g_signal_connect(w[0], "activate", G_CALLBACK(runner), w);

runner функция объявлена ​​как:

void runner(gpointer root, gpointer w[]);

Проверка значений массива w перед вводом runner и, пока он в нем, показывает, что они (значения) различны. Мне нужно, чтобы они были такими же. Как я могу сделать это, и почему они не идентичны? Кроме того, происходит segfault.


Я создал небольшую программу, которая полностью соответствует оригинальной и должна воссоздать условия, при которых возникает проблема. Как ни странно, все работает нормально.
#include <gtk/gtk.h>

void carry(gpointer root, gpointer a[])
{
        g_print("\n");                                                              
        g_print("%d\n", root);
        g_print("%d\n", a[0]);                                                      
        g_print("%d\n", a[1]);
        g_print("%d\n", a[2]);                                                      
}

int main(int argc, char **argv)
{
        gtk_init(&argc, &argv);                                                     

        GtkWidget *menu_item;
        GtkTextBuffer *buffer;
        gpointer abc[3];

        menu_item = gtk_menu_item_new();
        abc[0] = menu_item;
        g_print("%d\t%d\n", menu_item, abc[0]);
        menu_item = gtk_menu_item_new();
        abc[1] = menu_item;
        g_print("%d\t%d\n", menu_item, abc[1]);                                     
        buffer = gtk_text_buffer_new(NULL);                                         
        abc[2] = buffer;                                                            
        g_print("%d\t%d\n", buffer, abc[2]);

        g_signal_connect(abc[2], "modified-changed", G_CALLBACK(carry), abc);       

        gtk_text_buffer_set_modified(abc[2], TRUE);

        gtk_main();

        return 0;
}

Что означает, что что-то еще проблематично. Сейчас я попробую что-то еще, например, комментируя строки и оставляя только соответствующие.


Я еще не прокомментировал ни одной строки, но попытался ввести g_print как в вызывающую, так и в вызываемую строку.

Это вывод:

1162863440  1162863440
1162864736  1162864736
1163320992  1163320992

1162863440
-2
1162668992
973486176

Первые три строки сравнивают исходные значения с их копиями в массиве (в смысле g_print("%d\t%d\n", menu_item, abc[0]); из приведенного выше кода). Как видите, все назначено правильно. После новой строки мы проверяем те же значения в вызываемом. root, первый параметр, всегда имеет правильное значение. Так что с этим проблем нет. abc[0] в вызываемом всегда имеет значение -2 . Серьезно, каждый раз, когда я запускаю программу, это -2 . Другие два (abc[1] и abc[2]) всегда имеют некоторые случайные значения мусора, но они меняются каждый раз, когда я запускаю программу, в отличие от abc[0].

Надеюсь, это поможет в диагностике и устранении проблемы.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Вы не должны использовать gpointer s везде. gpointer - это void *, так что вы в значительной степени отключаете все проверки типов, которые компилятор может сделать для вас. Вместо этого используйте GtkWidget * и выполните правильное приведение, используя макросы G_OBJECT(), GTK_TEXT_BUFFER() и т. Д.

Вам также следует использовать типизированные аргументы обратного вызова, так как они появляются в документации для каждого сигнала. Например, для сигнала activate:

void
user_function (GtkMenuItem *menuitem,
               gpointer     user_data)

И если вы хотите передать несколько элементов в поле пользовательских данных, передайте указатель или указатель на структуру вместо массива указателей.

И если у вас есть segfault, просто используйте отладчик, чтобы проверить, в чем проблема.

0 голосов
/ 07 сентября 2018

Я попытался передать как abc[0], так и abc нормально через функцию (func(arg0, arg1, ...) вместо использования g_signal_connect()), и нет никаких проблем .

Все это может означать только одно: g_signal_connect портит мои ценности. Это меняет их по неизвестной причине.

Полагаю, мне придется использовать структуру.

...