电脑经常死机,其实很多原因都是堆栈的里面的指针错误的指向有关,那么这些都是些啥玩意,这么神奇导致了,能把电脑给搞死?下面针对里面的一些内部原因做下剖析,看看能不能解决大家的疑惑。
其实栈空间也是一块内存,只不过这块内存在应用起来的时候,由加载器loader负责向系统申请,应用程序不用操心这个事情。而内存的大小一般在编译的时候就决定了,编译器环境一般有可配置修改,但基本采用默认大小。所以不管哪种,一个应用程序的栈空间都是有限的。
其次,要知道的是栈空间跟线程是相关的,也就是说栈空间其实是分配到各个线程,在使用时也必须属于某一个特定的线程。因此每一个线程可以拥有的栈大小一般也是可以修改的,但是大多数情况,尤其是PC上的应用,这个栈空间也是基本采用默认就行。做过嵌入式的朋友应该很清楚,在嵌入式设备上,由于内存资源比较紧张,都尽量分配最小的栈空间给各个线程。所以对于线程来说,它能用的栈空间更是有一个限制,如果在该栈上开辟太多的变量或者很大的数组,就会导致运行时栈空间不够的情况,这就是栈溢出。发送栈溢出时,PC上一般应用程序崩溃,而在嵌入式系统上,差不多就直接死机了。
因此不要在栈上使用大量的空间,比如开辟很大的数组,递归函数的深度太大等等,都可能导致栈溢出,具体多大合适,要根据该线程的实际情况去分析,尤其是在嵌入式系统上更要注意,尽量做到既能保证线程正常工作,还要保证尽可能少用内存资源。
如何防止栈溢出呢?从上面的分析可以看出,自动变量就是从栈空间上分配,因此要防止栈溢出,就要有意识的不要从栈上分配较大空间。主要从以下几个方面来注意:
1,较大的数组,如果直接在函数中定义数组,则数组空间就会从栈中分配,比如int arr[1024];这个要放在函数中,则会占用4K的栈空间。如果需要这样的大空间,完全可以在堆上分配,大块的空间刚好适合堆分配的情况。
2,深度较大的递归,尤其是对递归的运行不太了解的情况,可能会有数千次甚至更多的调用,哪怕是函数中的自动变量不多,但是积累起来就不可小觑了。如果实在遇到这种嵌套的情况,应尽量改成非递归的调用方式。
3,要正确评估线程执行所需的空间和线程栈大小,在线程栈一定的情况下,要是线程任务足够复杂,即使注意到上面的情况,也可能会出现不够的情况。因此要正确根据线程的实际情况,设定线程栈大小。一般的系统都会有查看线程栈的实际占用大小的功能,要充分利用这些工具来评估实际栈空间的消耗。
这个话题到这里就算是说完了,我自己是名程序员,建了一个五千人群每天分享学习资料和学习方法:623532669,欢迎初学和进阶中的小伙伴。需要更多精彩内容,敬请关注小编!
邀请对编程感兴趣的小伙伴,一起玩编程,一起学代码,一起熬夜。
领取专属 10元无门槛券
私享最新 技术干货