« 被干眼症结膜炎困扰的这几年 | 返回首页 | 间断储存的字符串 »

skynet 1.6.0

最近半个月,因为广州防疫政策,我一直居家办公。找了点时间,给 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 去初始化指针。

Comments

指针计算的这段确实严谨!
看来要写出好的严谨的跨平台作品,精读标准C是必须的。

正好我最近遇到要写一段代码,也是用realloc重新申请内存,我的习惯是把以前的指针变成二进指针传递进去,然后把realloc申请的新地址赋值给原来的指针地址。感觉这样还挺方便的。

广州居家+1, 非游戏从业者,闲暇注册了招聘APP,看了看附近的一些游戏小厂招聘要求,发现很多公司都要求精通 skynet,俨然成为了行业标准 w

> 我的硬盘上留有几乎没有 Lua 发行版的源代码

几乎所有?

这里的确应该先算偏移。很多人在资源释放之后都是顺手把指针设为NULL,要是遇到喜欢自定义free顺手将free的旧指针设为NULL的,realloc之后继续用旧指针就血崩。

严谨确实是一个好的习惯

Post a comment

非这个主题相关的留言请到:留言本