栈溢出导致OS21 产生TLB missing

在开发ST5197平台中,碰到栈溢出导致程序崩溃
串口信息如下:
OS21: Stack trace (1 of 1)
OS21: Fatal exception detected: 0x00000040.
OS21: Data fetch TLB miss on address 0x0000001B


经过分析,是创建的线程分配stack size不够,造成栈溢出。
在这个搜索线程中,大量函数的频繁调用以及递归调用,大量的临时变量,以致于栈空间不够,程序崩溃。


解决方法:创建线程时,增大堆栈的大小。
创建线程的时候,可以通过pthread_attr_t来初始化线程的属性,包括线程的栈布局信息,如栈起始地址stackaddr, 栈大小stacksize。
 具体需要通过方法:

int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);  
// 注:stackaddr 指向为该线程开辟的空间,该空间可以使用malloc或者mmap来开辟,而不能来自进程的栈区。开辟的stackaddr所指向的动态空间需要自己负责释放。
 


【总结】栈溢出解决方案


方法一:用栈把递归转换成非递归
通常,一个函数在调用另一个函数之前,要作如下的事情:
a)将实在参数,返回地址等信息传递给被调用函数保存;
b)为被调用函数的局部变量分配存储区;
c)将控制转移到被调函数的入口. 

从被调用函数返回调用函数之前,也要做三件事情:
a)保存被调函数的计算结果;
b)释放被调函数的数据区;
c)依照被调函数保存的返回地址将控制转移到调用函数.
所有的这些,不论是变量还是地址,本质上来说都是"数据",都是保存在系统所分配的栈中的. 那么自己就可以写一个栈来存储必要的数据,以减少系统负担。 

方法二:使用static对象替代nonstatic局部对象
在递归函数设计中,可以使用static对象替代nonstatic局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销,而且static对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。

方法三:增大堆栈大小值
当创建一个线程的堆栈时,系统将会保留一个链接程序的/STACK开关指明的地址空间区域。但是,当调用CreateThread或_beginthreadex函数时,可以重载原先提交的内存数量。这两个函数都有一个参数,可以用来重载原先提交给堆栈的地址空间的内存数量。如果设定这个参数为0,那么系统将使用/STACK开关指明的已提交的堆栈大小值。后面将假定我们使用默认的堆栈大小值,即1MB的保留区域,每次提交一个页面的内存。

方法四:使用内存池

你可能感兴趣的:(Missing,栈溢出,tlb)