最近半个月,因为广州防疫政策,我一直居家办公。找了点时间,给 skynet 做了一年一度的 release 。
这次的 1.6.0 版,相比去年的 1.5.0 版,没有太大的变化。主要是平时积累的一些 bugfix 。它所依赖的第三方库,例如 Lua , jemalloc 我都更新到了最新的版本。
值得一提的是,mongo 的 driver 也更新了。因为 mongo 在最新的版本中已经淘汰了旧的 wire protocol ,如果再不更新,就无法连接新版 mongo server 了。具体讨论可以参看 PR #1649 。因为 mongo 自己的设计原因,我们无法给出一个同时兼容新老版本协议的方案。从这点来看,我个人认为 redis 的底层协议设计就稳定的多。 这么多年更迭基本不需要修改。
这些年,我一直在追踪 Lua 的更迭。我认为 Lua 的源代码是最值得一读的开源代码。作者的编码风格相当严谨,几乎每处细节都严格准循标准,而不仅仅只保证在现有环境下正确。这份严谨也并非从一开始就固有的,是这二十多年来逐步形成的。
我的硬盘上留有几乎所有 Lua 发行版的源代码,经常对比阅读。自从 Lua 在 github 上镜像了开发仓库后,我就习惯阅读它的每一个 commit ,经常能学到一些东西。
比如最近的这个:把 stack 的扩展从 free / copy / alloc 改成了 realloc 。
因为 realloc 可能会移动内存,引用 stack 内的地址的指针需要重新计算。如果以我通常的做法,求出新老地址的偏移量,然后加在新地址指针上就好了。
但是 Lua 的作者选用了另一种方案:在 realloc 生效之前,将指针转换为 stack 的 offset ;realloc 之后再转换为新指针。它这样做的原因是:
In ISO C, any pointer use after the pointer has been deallocated is undefined behavior. So, before the reallocation, all pointers are changed to offsets, and after the reallocation they are changed back to pointers.
就是说,ISO C 对使用被释放的指针的行为是未定义的。这里指的是使用,而不仅仅是解引用。我相信现存的硬件上,对释放的指针地址本身做计算都是安全的,但这种正确性从标准来说,还是属于未定义的行为。
记得前段时间在 Lua 的邮件列表中还看到过关于指针的另一处讨论:Lua 的作者解释为什么没有用 memset 0 初始化包含有指针的数据结构。他说,从标准的定义看,NULL 未必是数值 0 。所以必须用 = NULL 去初始化指针。