常见坑
每一章对着一个报错或一个现象:先用最小的程序把它复现出来(输出是 M2 Max、rustc 1.99.0 上的原文),再到源码里找它从哪一行来,最后给出修法和检查办法。机制在前面几部分讲过的,这里只链过去,不再重复。
- 一个小切片让整块缓冲一直不释放:切片和原缓冲共享同一块分配;在 hyper 里把 1000 个 32 字节的请求头值存进长期容器,留住约 8 MiB 读缓冲,
copy_from_slice后只剩 32 000 字节;split的时机决定留住哪一块;1.12.1 的clear()不放手。 - range end out of bounds 与 split_to out of bounds:
slice、split_to、split_off、extend_from_within越界的原文和出处;panic 报在bytes.rs/bytes_mut.rs而不是调用行,因为只有range标了#[track_caller];怎么用回溯找到自己那一行,怎么不 panic 地切。 - index out of bounds: the len is 0 but the index is 0:
with_capacity只给容量;按下标写 panic,read(&mut buf)返回Ok(0)像 EOF,split_off能切进没写的容量;用put_*、resize、zeroed、read_buf。 - advance out of bounds: the len is 3 but advancing by 4:
get_*在半包上 panic;直接在缓冲上try_get_u32会读走长度、让整条流错位;先在副本上 peek,整帧到齐再消费。 - try_get_int 把 -1 读成 16777215:1.10.0 到 1.12.1 的
try_get_int/_le/_ne不做符号扩展;修复 #839 已合进 master 未发版;替代写法和一条升级后会变绿的测试。 - reserve 之后,备用容量里写的字节变了:往备用容量里写了、还没
set_len就reserve,这些字节不会被保留;有切片活着时reserve只按需分配、不翻倍;with_capacity(0)出生的缓冲原始容量是 0。 - remaining() 是 25,chunk() 只有 8 个字节:把
chunk()当成全部数据的解析器,在Chain这类不连续的Buf上找不到分隔符或切定长字段时 panic。 - try_into_mut 返回 Err:还有别的句柄;或者存储是
from_static/from_owner,永远是Err。 - unsplit 之后前后两段对调了:顺序反了不报错,内容被静默拷贝追加;
split_off越过长度后unsplit丢容量;try_unsplit返回Ok不代表来自同一块缓冲。
flowchart TB
q{碰到了什么}
q -->|内存只涨不降| p1["1 小切片留缓冲"]
q -->|"out of bounds panic"| pp{哪一种}
pp -->|"slice / split"| p2["2 越界"]
pp -->|"the len is 0"| p3["3 容量不是长度"]
pp -->|"advance out of bounds"| p4["4 半包"]
q -->|数值不对| p5["5 try_get_int"]
q -->|"BytesMut 行为意外"| bm["6 reserve 或 9 unsplit"]
q -->|"Chain 解析出错"| p7["7 Chain"]
q -->|"转不回 BytesMut"| p8["8 try_into_mut"]
💬 关联讨论
发起讨论加载中...