You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GTK中GTK_IS_WIDGET断言失败求助:复用ComboBox异常

Gtk复用ComboBox触发断言失败的原因及解决办法

问题场景

为减少gtk_combo_box_text_new()的调用次数,将ComboBox改为全局数组声明复用:

static GtkWidget *apo_combobox[NUM_MPI_MEAS];

在弹窗首次初始化时创建并初始化ComboBox,首次打开弹窗正常,但隐藏后再次打开时,执行gtk_grid_attach触发如下错误:

Gtk-CRITICAL : 10:35:18.106: gtk_grid_attach: assertion 'GTK_IS_WIDGET (child)' failed

异常代码片段:

void init_popup() {

  if (!j_first_show) {
    apo_combobox[i] = gtk_combo_box_text_new();
    init_combobox(i);
    // 创建窗口和布局的代码,网格也在此初始化
  }
  
  for (int i = 0; i < 10; i++) {
    gtk_grid_attach(GTK_GRID(meas_assign.po_grid), apo_combobox[i], 1, j_track_button_placement, 1, 1);
  }
}

打印apo_combobox元素地址未变化,但断言仍失败。

核心原因

  1. 初始化逻辑漏洞:
    初始化块中使用了未定义的变量i,仅给数组中某个随机索引的ComboBox赋值,其余元素为全局静态数组默认的NULL。循环执行gtk_grid_attach时,NULL指针无法通过GTK_IS_WIDGET断言,直接触发错误。

  2. Widget生命周期错误:
    若弹窗隐藏时调用gtk_widget_destroy()而非gtk_widget_hide(),首次创建的网格和ComboBox会被彻底销毁。此时apo_combobox中的指针虽地址未变,但指向的是已被GTK回收的无效内存,不再是有效Widget实例。

  3. 重复容器关联冲突:
    即使ComboBox已正确初始化,若弹窗仅隐藏未销毁,再次调用gtk_grid_attach时,ComboBox仍属于之前的网格容器。GTK不允许一个Widget同时属于多个容器,虽会自动移除原关联,但原网格状态异常时也可能触发断言失败。

修复方案

1. 修正初始化循环

在首次初始化时遍历数组,创建所有ComboBox实例,并标记初始化完成:

void init_popup() {
  if (!j_first_show) {
    // 批量创建并初始化所有ComboBox
    for (int i = 0; i < NUM_MPI_MEAS; i++) {
      apo_combobox[i] = gtk_combo_box_text_new();
      init_combobox(i);
    }
    // 创建窗口、网格等布局代码
    // 标记为已完成首次初始化
    j_first_show = TRUE;
  }
  
  for (int i = 0; i < NUM_MPI_MEAS; i++) {
    // 先检查Widget有效性
    if (GTK_IS_WIDGET(apo_combobox[i])) {
      // 移除可能存在的父容器关联
      GtkWidget *parent = gtk_widget_get_parent(apo_combobox[i]);
      if (parent != NULL) {
        gtk_container_remove(GTK_CONTAINER(parent), apo_combobox[i]);
      }
      // 调整布局索引(示例中j_track_button_placement需按实际需求偏移)
      gtk_grid_attach(GTK_GRID(meas_assign.po_grid), apo_combobox[i], 1, j_track_button_placement + i, 1, 1);
    }
  }
}

2. 正确管理弹窗生命周期

使用gtk_widget_hide()隐藏弹窗,而非gtk_widget_destroy()。这样网格和ComboBox实例会被保留,下次打开时直接复用,避免重复创建或无效指针问题。

3. 添加有效性前置检查

在调用gtk_grid_attach前,始终用GTK_IS_WIDGET()宏验证apo_combobox[i]的有效性,过滤空指针或无效实例。

内容的提问来源于stack exchange,提问作者anon1234

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:10:40