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后,打印的字符串异常情况更严重。
解决方案
原因分析
- 原始
char Name[32]写法中,核心问题是ImVector的拷贝/内存管理逻辑异常,导致Pin的Name数组指向已释放或未正确初始化的内存区域,从而显示乱码。 - 改用
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
相关产品推荐
相关产品推荐

