作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
先看导致问题的核心代码:
func ZeroAllocString() string {
// 为了不分配内存,存储空间总是从 pool 获得
buf := pool.Get().([]byte)
// 业务采用了类似 arena 分配的策略,在一大个池子里面放自己的数据
temp := buf[10: 10: 4]
temp = append(temp, "abcd"...)
s := unsafe.String(unsafe.SliceData(temp), len(temp))
// 退出生命周期后,回收内存块,以便下次重用
clear(buf) // 这里相当于 memset(ptr, 0), "abcd" 这个字符串的内容已经丢失
buf = buf[:0]
pool.Put(buf)
// 但是部分对象已经跳出了所依赖内存的生命周期
return s
}
总结:
- 一旦用上 unsafe,就要非常非常小心,驾驭不住就会出问题;
- 内部的指针错从复杂的指来指去的时候,一定要考虑各个依赖对象的生命周期是否对等
- 特别是实现一个库的时候:使用者只看见了 string,并不知道简单的用个 string 也会出问题。

浙公网安备 33010602011771号