编写SHA-256哈希计算函数时,是否需要调用crypto.Hash.destroy?
我实现了一个简单函数,传入字符串后返回其SHA-256哈希值(十六进制形式),代码如下:
function computeSHA256Hash(string) { const hash = crypto.createHash('sha256'); hash.update(string); return hash.digest('hex'); }
注意到crypto.createHash返回的crypto.Hash对象有一个destroy方法,想问下是否需要调用这个方法?下面是我写的带调用destroy的示例代码:
function computeSHA256Hash(string) { let hash; try { hash = crypto.createHash('sha256'); hash.update(string); return hash.digest('hex'); } finally { if (hash) { hash.destroy(); } } }
回答
先说结论:大多数日常场景下,你根本不需要手动调用destroy方法
当你调用
hash.digest('hex')之后,Node.js会自动清理这个Hash对象的内部资源,包括底层的加密句柄。这时候Hash对象已经处于不可用状态了,再调用destroy完全是多此一举。只有一种情况需要考虑调用
destroy:如果你的代码逻辑里,存在还没调用digest就提前退出的可能(比如中途抛出错误、走了某个分支直接返回),这时候Hash对象还握着没释放的资源,用finally块兜底调用destroy能主动释放资源,避免潜在的内存泄漏。但看你第一个版本的代码,是顺顺利利执行完digest才返回的,不存在这种提前退出的情况,所以加finally完全没必要。退一步说,就算你真的忘了在极端场景下调用
destroy,Node.js的垃圾回收机制最终也会把这些没人用的Hash对象回收掉,释放资源。只不过主动调用destroy能让资源释放更及时,但对你这种短生命周期的函数来说,这点影响几乎可以忽略。
总结:你的第一个版本代码就足够简洁正确,没必要画蛇添足加destroy的调用。只有当Hash对象可能在未完成digest就被丢弃时,才需要考虑用finally确保资源被释放。
内容的提问来源于stack exchange,提问作者Abdelfattah Radwan

