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

ImGui::Text无法正常显示ImVector<Pin>中字符串的问题求助

问题:打印Pin名称时出现乱码

尝试在屏幕上打印Pin的名称,但显示乱码。将Name改为std::string后,异常情况更严重。

类定义代码

struct Pin
{
    int ID;
    char Name[32];

    Pin(int id, const char *name)
    {
        ID = id;
        strcpy(Name, name);
    }
};

struct Node
{
    int ID;
    char Name[32];
    ImVec2 Pos, Size;
    float Value;
    ImVector<Pin> Inputs, Outputs;

    Node(int id, const char *name, const ImVec2 &pos, const ImVector<Pin> inputs, const ImVector<Pin> outputs)
    {
        ID = id;
        strcpy(Name, name);
        Pos = pos;
        Inputs = inputs;
        Outputs = outputs;
    }

    ImRect GetInputFlowSlotPos(ImVec2 offset) const
    {
        return ImRect(offset + ImVec2(Pos.x + 24.0f, Pos.y + 44.0f), offset + ImVec2(Pos.x + 4.0f, Pos.y + 24.0f));
    }
    ImRect GetOutputFlowSlotPos(ImVec2 offset) const
    {
        return ImRect(offset + ImVec2(Pos.x + Size.x - 24.0f, Pos.y + 24.0f), offset + ImVec2(Pos.x + Size.x - 4.0f, Pos.y + 44.0f));
    }
    ImVec2 GetInputSlotPos(int slot_no) const { return ImVec2(Pos.x, Pos.y + Size.y * ((float)slot_no + 1) / ((float)Inputs.Size + 1)); }
    ImVec2 GetOutputSlotPos(int slot_no) const { return ImVec2(Pos.x + Size.x, Pos.y + Size.y * ((float)slot_no + 1) / ((float)Outputs.Size + 1)); }
};

初始化代码

inputsPin.push_back(Pin(0, "X"));
inputsPin.push_back(Pin(1, "Y"));
inputsPin.push_back(Pin(2, "Z"));

nodes.push_back(Node(0, "Di", ImVec2(40, 50), inputsPin, outputsPin));
nodes.push_back(Node(1, "Di", ImVec2(40, 150), inputsPin, outputsPin));
nodes.push_back(Node(2, "Di", ImVec2(270, 80), inputsPin, outputsPin));

打印代码

for (int slot_idx = 0; slot_idx < node->Inputs.Size; slot_idx++)
{
    Pin *pin = &node->Inputs[slot_idx];

    ImGui::SetCursorScreenPos(offset + node->GetInputSlotPos(slot_idx));
    ImGui::Text("%s", pin->Name);
}

*编辑:将Name改为std::string后,打印的字符串异常情况更严重。


解决方案

原因分析

  1. 原始char Name[32]写法中,核心问题是ImVector的拷贝/内存管理逻辑异常,导致Pin的Name数组指向已释放或未正确初始化的内存区域,从而显示乱码。
  2. 改用std::string后问题加剧,说明ImVector对非POD复杂类型的拷贝、移动操作支持不完善,引发了更深层的内存访问错误。

修复方案

方案1:完善自定义类型的拷贝逻辑

给Pin添加显式的拷贝构造函数和赋值运算符,避免ImVector进行浅拷贝:

struct Pin
{
    int ID;
    char Name[32];

    Pin(int id, const char *name)
    {
        ID = id;
        strncpy(Name, name, sizeof(Name)-1); // 用strncpy避免缓冲区溢出
        Name[sizeof(Name)-1] = '\0'; // 手动添加字符串终止符
    }

    // 显式拷贝构造函数
    Pin(const Pin& other)
    {
        ID = other.ID;
        strncpy(Name, other.Name, sizeof(Name));
    }

    // 赋值运算符重载
    Pin& operator=(const Pin& other)
    {
        if (this != &other)
        {
            ID = other.ID;
            strncpy(Name, other.Name, sizeof(Name));
        }
        return *this;
    }
};

方案2:替换为std::vector容器

ImVector是ImGui自定义容器,对复杂类型的兼容性不如标准库的std::vector。将Node中的ImVector<Pin>替换为std::vector<Pin>,无需额外修改初始化和打印逻辑:

struct Node
{
    // ... 其他成员不变
    std::vector<Pin> Inputs, Outputs;
    // ... 构造函数和方法不变
};

方案3:使用智能指针避免拷贝

如果不想处理拷贝逻辑,改用智能指针存储Pin实例,彻底避免内存拷贝问题:

struct Node
{
    // ... 其他成员不变
    ImVector<std::unique_ptr<Pin>> Inputs, Outputs;

    // 调整构造函数参数
    Node(int id, const char *name, const ImVec2 &pos, ImVector<std::unique_ptr<Pin>> inputs, ImVector<std::unique_ptr<Pin>> outputs)
    {
        ID = id;
        strcpy(Name, name);
        Pos = pos;
        Inputs = std::move(inputs);
        Outputs = std::move(outputs);
    }
};

// 初始化代码调整为
inputsPin.push_back(std::make_unique<Pin>(0, "X"));
inputsPin.push_back(std::make_unique<Pin>(1, "Y"));
inputsPin.push_back(std::make_unique<Pin>(2, "Z"));

额外注意事项

  • 始终用strncpy替代strcpy,防止输入字符串长度超过数组容量导致缓冲区溢出,破坏内存结构。
  • 检查node->Size.y的值是否合法,如果为0,GetInputSlotPos会触发除零错误,间接引发内存访问异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:55:21