LINUX.ORG.RU

Молчаливый сегфолт при втором вызове

 , , ,


0

1

Дано:

  • дерево (пустое, то есть голое, поэтому скриншотов не будет, т. к. ему ещё не исполнилось 18 лет);
  • тестовый обработчик.

Цель: создавать пару родительский — дочерний узел, причём так, чтобы родительские узлы не повторялись (т. е. если уже найден родитель с таким именем, дочерний узел цепляется ему).

Говнокод обработчика:

	GValue* cur_gvalue;
	gchar* cur_string;
	GtkTreeIter app, notification;
	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(drugStore), &app))
		goto apps_empty;
	do {
		g_value_unset(cur_gvalue);
		gtk_tree_model_get_value(GTK_TREE_MODEL(drugStore), &app, 0, cur_gvalue);
		if (!g_strcmp0(g_value_get_string(cur_gvalue), "tist")) {
			goto app_exists;
		}
	} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(drugStore), &app));
	apps_empty:
	gtk_tree_store_append(drugStore, &app, NULL);
	gtk_tree_store_set(drugStore, &app, 0, "tist", -1);
	app_exists:
	gtk_tree_store_append(drugStore, &notification, &app);
	gtk_tree_store_set(drugStore, &notification, 0, "tist2", -1);
При втором вызове (когда один узел уже есть и заходит в цикл) сегфолтится на gtk_tree_model_get_value. Молча. Номер колонки правильный, соседние значения проверял, с типами вроде всё в порядке, что ещё может быть? Воспроизводится на GTK2 и GTK3, так что баг вряд ли в тулките.

причина в

Говнокод

решение - gdb

/thread

anonymous ()

Что-то прямо адовый говнокод какой-то. Поработай над логикой. Дебаж в gdb что тут еще можно сказать? Собери дамп и дебаж.

hibou ★★★★★ ()

goto apps_empty
goto app_exists

Перепиши и проблема уйдёт. Инфа 100%

ziemin ★★ ()

g_value_unset(cur_gvalue);

В первый раз не вылетает только потому что undefined behavior. Что вообще заставило писать GUI на C? Если уж писать на GTK (что само по себе упорото в 2015 году), то на чем-то более подходящем (python, vala, gtkmm).

crowbar ()

Пожалуйста. Сделай всем одолжение. Больше не пиши код. Никогда.

anonymous ()

запусти из gdb, сделай так, чтоб упало, напечатай bt

Harald ★★★★★ ()

Если ты только начал изучать GTK, почитай вот это https://developer.gnome.org/gobject/stable/pt02.html

Это то, что тебя ждет если тебе захочется написать свой виджет (или даже поправить существующий).

crowbar ()
Ответ на: комментарий от crowbar

Clears the current value in value and «unsets» the type, this releases all resources associated with this GValue. An unset value is the same as an uninitialized (zero-filled) GValue structure. https://developer.gnome.org/gobject/stable/gobject-Generic-values.html#g-valu...

Там вон пишут, что очищенное значение - это то же что и не инициализированное. Но меня больше пугает другая часть фразы - this releases all resources associated with this GValue. Вот, а он туда вроде указатель передал. Может оно ему полтаблицы пытается релизнуть нафиг? ну в смысле из памяти ее тогось... не?

hibou ★★★★★ ()
Ответ на: комментарий от hibou

Я понял — он туда неинициализированный указатель передает.

crowbar ()

Я хотел было написать про то, как valgrind помогает искать лишие free/обращение к неинициализированной области памяти, как вдруг увидел

g_value_unset(cur_gvalue);
И что же там по-твоему находится, а? В двух словах твоя проблема: ты неправильно работаешь с GValue. Есть мнение, что должно быть
GValue cur_value[1];
g_value_init(cur_value, G_TYPE_NONE);
...
do {
  gtk_tree_model_get_value(GTK_TREE_MODEL(drugStore), &app, 0, cur_gvalue);
  /* do smth with value */
  g_value_unset(cur_value);
} while (...);

P. S. на gtk не пишу, настоятельно рекомендую тебе RTFM.

kawaii_neko ★★★★ ()

http://i.imgur.com/7EcATNf.jpg

Я не думаю, что написав такой код ты осилишь отладку в gdb. Поэтому просто перепиши его нормально.

Deleted ()

по делу всё написано, поэтому спрошу не очень по делу

if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(drugStore), &app))
	do {
		g_value_unset(cur_gvalue);
		gtk_tree_model_get_value(GTK_TREE_MODEL(drugStore), &app, 0, cur_gvalue);
		if (!g_strcmp0(g_value_get_string(cur_gvalue), "tist")) {
			goto app_exists;
		}
	} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(drugStore), &app));
	gtk_tree_store_append(drugStore, &app, NULL);

почему не?

next_time ★★★★★ ()
Ответ на: комментарий от next_time

Мэтры говорят, что бояться goto не нужно. Поэтому чем больше goto ты напишешь, тем меньше ты боишься.

anonymous ()
Ответ на: комментарий от anonymous

Мэтры(ака нескромники Дейкстры) грят чем схожей текст программы и её исполняемый процесс тем легче это умопостигать.

qulinxao ★★☆ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.