GTK4中多选时gtk_tree_selection_get_selected_rows返回NULL路径致崩溃
问题分析与修复方案
你的代码崩溃并非GTK4的bug,而是存在两个关键实现错误:
错误原因
- GList访问方式错误:GList是GLib单向链表结构,不能通过
selected_list[i]这种数组下标方式直接访问元素,这种写法会触发未定义行为,可能读取到NULL或错误内存地址。 - 删除顺序导致路径失效:从前往后删除行时,每删除一行,
GtkListStore中后续行的位置会自动前移。比如删除第0行后,原第1行变为新第0行,但你保存的TreePath仍指向原位置(路径值为1),此时用该路径获取迭代器会得到错误结果甚至NULL,最终引发段错误。
修复后的代码
static void delete_selected_rows(GtkButton *activated, GtkTreeView *tree_view) { GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(tree_view); GtkTreeModel *model; GList *selected_list = gtk_tree_selection_get_selected_rows(tree_selection, &model); // 反转链表,从最后一行开始删除,避免路径失效 GList *reversed_list = g_list_reverse(selected_list); for (GList *l = reversed_list; l != NULL; l = l->next) { GtkTreePath *path = l->data; GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gtk_list_store_remove(GTK_LIST_STORE(model), &iter); } } g_list_free(reversed_list); g_list_free_full(selected_list, (GDestroyNotify)gtk_tree_path_free); }
修复说明
- 反转链表调整删除顺序:通过
g_list_reverse()将选中路径链表反转,从最后一行开始删除,这样前面行的删除操作不会影响后续(当前遍历的)路径有效性。 - 标准GList遍历方式:使用
GList原生的链表遍历逻辑访问元素,彻底规避数组下标访问的错误。 - 添加有效性检查:对
gtk_tree_model_get_iter()的返回值做判断,即使路径意外失效也不会执行后续删除操作,进一步提升代码稳定性。
内容的提问来源于stack exchange,提问作者Fedor S
相关产品推荐
相关产品推荐

