爆栈(stack overflow), 众所周知是一种软件的致命错误, 一旦发生程序就core了。根据维基百科的描述,当代码中有以下三种情形时会引发爆栈
- 无限递归
- 函数调用链展开过深
- 函数内申请过大的局部变量
其中1.和2.本质上是相同的,不管是否递归,只要函数调用链过深,压栈过多就会引发爆栈。只不过在实践中,由递归更容易引发爆栈。
可是在很多时候,我们无法避免递归。比如数据库在对SQL语句的执行实现中,伴随着输入的SQL语句的复杂性,间接递归通常是可以预见的。但是无论哪种情况,我们都不能容忍一个用户输入导致程序爆栈,因此这种情况下,我们就需要一个防爆栈机制
下文通过介绍我经手的一个防爆栈机制的实现过程,分享一下有关程序设计的教训与心得:
由于手头当前的工作是基于PostgreSQL(以下简称PG)做二次开发,因此目前对PG的源码也或多或少地读了一些,因此便想到了在博客里分享一些关于阅读PG源码所获得的KnowHow。
在国内的PG技术圈内,提到PG源码解读自然首推武汉大学的两位彭老师所著的《PostgreSQL数据库内核分析》。不过这本书的着眼点是对PG源码的整体架构,以及SQL引擎,存储系统,事务处理等等这些实现机制&算法的介绍,而我则主要想分享一些PG代码中的一些有意思的小细节/小功能。虽然只是PG那几百万行源码中的沧海一粟,不过从这些小细节中解读程序设计的匠心也是颇有意思的。
第一篇就从PG中无处不在的OID开始吧
在涉及到并发编程的情况下,经常性地会碰到一种场景:
由一个线程开启了多个线程并发执行多个任务,之后由该线程(so called “主线程”)等待多个线程都结束后汇总结果.
这种场景下,主线程在其创建的子线程执行期间内需要阻塞,直到其他子线程都执行完毕。由于这类场景已经在不同语言的开发中遇到多次,所以汇总一下这些语言的常用实现方法,以后查起来也方便~