头像
  • 主页
  • 文章
  • 标签
  • 文件
所有文章 友情链接 关于我


本站支持SSL安全访问
本站支持IPv6访问


MySSL 安全签章
头像

  • 主页
  • 文章
  • 标签
  • 文件

吞吞吞:热爱吞字的 std::wstring_view

2025-11-07

事情起因

作为一名喜欢 PaperMC 控制台样式的 MC 玩家,我在尝试用 C++ 来还原一些 PaperMC 当中的控制台样式。我的 KlyLogger 就仿照了 PaperMC 的样式。
可是光有输出模仿出来了,输入还没有,这也不够啊?奈何 C++ 里没有现成的 JLine 移植版,而我又不想再自己造轮子了 (其实是技术不到位) ,那我也只好在互联网上翻翻看咯。好在,我在 GitHub 上翻到了 replxx 这个库来处理用户输入,还搜出来了 C++ 版本的 brigadier: brigadier-plus-plus (其 README 里写明灵感来源于 Mojang 的 brigadier),但人家又使用的不是宽字符串,在遇到命令解析异常时抛出的错误信息可能就把一个完整的字截断,导致字符串无法解码 (如下图)。
命令解析异常输出 (正常)
命令解析异常输出 (异常)
于是,便有了接下来的故事…

大刀阔斧的“升级”

在我打开 brigadier.hpp 这个头文件准备开始动刀时,猛然发现这家伙竟然有足足三千行,这我要是挨个挨个改得改到什么时候啊?所以… Ctrl-H!直接查找 std::string 全部替换为 std::wstring !再把 char 全部替换为 wchar_t !再根据编译时的报错做点小调整!堪比完…美…??
然而当我兴致冲冲运行代码时,却发现… 我的高亮和 Tab 补充怎么炸了???

改动之前的效果 改动之后的效果
改动之前的效果 改动之后的效果
(其中,屏幕闪烁代表触发 beep,表示该操作无效)
得,又得潜入那三千行代码的汪洋,去寻找那根深藏的刺了…

该死的“贪吃虫”

历经千辛万苦,终于在检查 brigadier::StringReader 构造函数接收的字符串时发现了问题所在: std::wstring_view 这家伙居然把命令的第一个字符给吞了!
解决方式简单粗暴——弃用 std::wstring_view ,换回 std::wstring !性能?Who cares?能跑起来才是王道!

贪吃虫的进食原理

“为什么会这样?”——我也很想知道。于是我开始查阅 string_view 相关的内容,这才恍然大悟:
原来, std::wstring_view 本质上是个”视觉小偷”,它只负责看,不负责管饭:

1
2
3
4
5
6
7






std::wstring_view viewer;
{
std::wstring text_string = L"text";
viewer = (text_string);
}
// text_string 离开作用域,内存被回收
// viewer 还在指着那片已经"过期"的内存地址






问题核心: std::wstring_view 只是个轻量级的”视图”,它不拥有实际的数据。当原始字符串的生命周期结束时, std::wstring_view 还在那傻乎乎地指着已经释放的内存。
所以根本不是它故意”吞”字,而是整个字符串都处于”薛定谔的猫”状态——你永远不知道读取时看到的是什么!

(可又为什么之前的 std::string_view 就不会吞字呢…也许只是运气好吧?)

(我说到底也只是个小白,哪懂这些复杂的东西…)

参考文本

标准库头文件 (C++17) - cppreference.cn - C++参考手册
C++std::string_view完全指南:高性能字符串处理详解 · C++ 编程指南

  • Coding
  • Cpp
KlyLogger
  1. 1. 事情起因
  2. 2. 大刀阔斧的“升级”
  3. 3. 该死的“贪吃虫”
  4. 4. 贪吃虫的进食原理
  5. 5. 参考文本

版权 © 2022~2025 KTK::KinnerFisch - 采用 CC BY-NC-SA 4.0 进行许可
Powered by Hexo with Yilia theme, served by Jetty , hosted on Akile .
  • 所有文章
  • 友情链接
  • 关于我

tag:

  • Minecraft
  • Music
  • Scribbles
  • Library
  • Coding
  • Cpp
  • oines 的主页
会咕咕咕的鸽子一只