最近的项目是在 Itron 系统上完成一个UI系统的设计,为了提高效率我用VC在 Windows 上做了一个模拟环境,大家在 Windows 上完成程序的开发并进行逻辑测试后再用专用的编译器编译,下载到硬件上测试。
在向客户交演示程序的前期,在硬件上跑的程序总是出现 Memory 访问不正的错误。开始没有引起我的注意,认为是组内人员在使用指针上出了问题,他们可以改正的。
但经过一周后这个问题还是经常出现,我就不得不亲自调查了。
我通过排查发现是一个界面引起的问题,在这个界面上我又发现是画两个图片时出现的问题。于是,最简单的我认为是这两个图片格式上有些不妥,但总找不到解决问题的方法。
在经过两天的调查后问题还没有解决,我只得在其它方面想。最终我想到,是不是线程堆栈溢出了呢。
原来,在 Itron 中线程是静态分配的,在配置文件中可以定义线程的栈空间,原来我把栈大小定义为 400 个字节,于是我试着把空间改为 1000 个字节,呵呵,问题解决了。
那么,仔细思考下。原来我为了防止大家格式化字串出错,写了一个格式化字串函数,在函数中我定义了一个临时变量数组,他的大小是 256 个字节(现在想想有些疯狂),结果这个函数一执行就出错。因为当时我忙于程序框架的再整理没有仔细理会这个问题,只是简单的把这个函数注掉,告诉大家等我以后再处理,现在想想,问题出在了线程堆栈溢出上。
现在总结下线程栈的作用:
1.函数中的临时变量是在线程栈中分配的。
2.在调用函数前要将当前的地址入栈,以备函数返回时用。
3.函数的参数是要入栈的。
那么根据上面的分析,我总结了下面的注意事项:
1.限制函数中的临时变量的大小,不要定义超过占内存 50 个字节的变量,如果有需要要定义成全局或静态变量。
2.函数的参数也不要定义的太大,尽量使用指针。(因为是C语言,所以不能使用引用)
3.尽量在函数中少定义临时变量,因为每个临时变量虽然小,但如果定义的多了也会出现问题。
4.尽量把窗口函数的变量定义在窗口预先分配好的空间中,因为窗口的内存空间是预先分配好的,如果不用实在可惜。毕竟全局变量可用的空间只有 31K,也是经不住浪费的。
如果遵守上述规则,可以大幅度的减少线程栈溢出的危险。
在 Windows 下编程,线程栈的空间默认为 1M,所以我们很少出现线程栈溢出的情况。如果想观察这种情况,我们可以用下面两种方法测试
1.在函数中定义一个足够大的数组,可以定义为 int a[10000],数组大小可以自己试,程序直接崩溃就说明成功了。
2.写一个没有退出条件的无限递归函数,调用下,直到程序崩溃为止。