ImGui渲染TCP套接字接收文本时出现乱码问题求助
问题分析与解决方案
核心问题:野指针导致内存访问失效
你的代码中出现乱码的根本原因是**card_data结构体存储的是临时字符串对象的指针,当临时对象销毁后,指针变为野指针**,后续渲染时访问已释放的内存,导致随机字符或'?'。
具体原因:
- 循环中
splitString(token, '_')返回的std::vector<std::string>是局部对象,每次循环迭代结束后会被销毁,内部的std::string对象也会被释放。 dist[0].c_str()返回的指针仅在dist对象存活期间有效,当dist销毁后,该指针指向的内存被回收,变为无效指针。- 控制台打印时
dist尚未销毁,所以能正常输出;但texts.push_back存入的是无效指针,后续渲染时访问已释放的内存,出现乱码。
另外,原代码还有两个潜在问题:
- 结构体的
operator==使用std::wcscmp比较窄字符指针,类型不匹配,会导致未定义行为。 - TCP接收时未处理
recv的返回值,直接用strlen(drecv)判断长度,可能因未接收完整数据或数据包含'\0'导致错误。
解决方案
1. 修改card_data结构体,存储std::string而非指针
将结构体中的const char*成员改为std::string,避免依赖临时对象的指针:
struct card_data { std::string content; std::string label1; std::string label2; bool operator==(const card_data& other) const { return label1 == other.label1; // 直接使用std::string的比较运算符,安全可靠 } };
2. 调整接收逻辑,直接存入std::string
在循环中直接将分割后的字符串存入结构体,不再依赖临时指针:
while (std::getline(ss, token, '/')) { std::vector<std::string> dist = splitString(token, '_'); std::string label1 = dist[0]; std::string label2 = dist[1]; std::string content = dist[1]; // 注意:原代码content与label2取值相同,确认是否为预期逻辑 std::cout << label1 << std::endl; std::cout << label2 << std::endl; std::cout << content << std::endl; texts.push_back({ content, label1, label2 }); }
3. 调整渲染调用,传递std::string的c_str()
在渲染循环中,通过c_str()将std::string转换为const char*传递给渲染函数:
// 主循环中的渲染部分 for (const auto& text : texts) { ImGui::LabelledCard(text.content.c_str(), text.label1.c_str(), text.label2.c_str()); }
4. 修复TCP接收的长度处理问题
正确处理recv的返回值,确保字符串正确终止:
char drecv[300]; int bytes_received = recv(_conn, drecv, sizeof(drecv) - 1, 0); // 预留一个字节放'\0' if (bytes_received <= 0) { // 处理连接错误或关闭的情况 return; } drecv[bytes_received] = '\0'; // 手动添加字符串结束符 // 后续的空格清理逻辑不变 size_t length = strlen(drecv); while (length > 0 && isspace(drecv[length - 1])) { drecv[--length] = '\0'; }
内容的提问来源于stack exchange,提问作者OpperDev
相关产品推荐
相关产品推荐

