【100莫元】堆栈溢出导致的hardfault和数据访问违例异常
堆栈溢出后,内存被踩了(已经验证过),开始没事,踩完之后还是可以运行的,堆栈溢出真恐怖,接着运行,最后进入了硬fault。被我找到一句进入hardfault的语句,然后查找到那句话的汇编是“STR r3,”,然后就死了。
接着打印出硬fault的寄存器的值查得是“硬fault 是被上访的。上访者可以是总线fault、存储器管理 fault或是用法 fault”。
我再打印出其他的异常的寄存器,查得是总线fault的不精确的数据访问违例。
请大神们,联想下“STR r3,”和这个异常是神马情况,这句汇编对应的C语言是一个赋值语句,而且赋值给的这个内存单元在堆栈溢出的时候被修改过。
只要回复好我这个,相当于在其他的帖子回复100个啊,有能力的赶紧回复下。
突然好心痛啊,发了个帖子丢了100莫元。 主要是指针错误;
这个只有你自己才能找到BUG hhxb 发表于 2014-12-18 21:14
主要是指针错误;
这个只有你自己才能找到BUG
请大神明示。 在hardfault函数断点,打开Call stack,查看其中进入hardfault前的调用函数,就知道可能出现在哪个函数里了!主要关注指针溢出、内存访问溢出等等情况!当然调用不安全的库函数也会出问题! 本帖最后由 security 于 2014-12-18 21:43 编辑
这条语句是一赋值语句,
将R3的东西,赋值到R0作为基址,0xb4为偏移的内存地址。
这里的异常,属于暴力访问,通常是指向了非法的地址
在VC上,如果访问了非法地址,也会抛出类似异常
因此,你这边重点是 R0的内容,被篡改了
导致的地址非法了。
具体是谁动了R0,那就是你程序栈溢出影响到了
剩下,就等你继续分析,告知大家了
(不为莫元,只为积分,今天终于升级为中级会员了,喜大普奔啊) 可惜没学好汇编,看着100莫元好心动啊。替楼主顶一下,攒个人气,早日解决bug
security 发表于 2014-12-18 21:23
这条语句是一赋值语句,
将R3的东西,赋值到R0作为基址,0xb4为偏移的内存地址。
这里的异常,属于暴力访问 ...
我根据寄存器的值发现没有问题啊,访问的是一个数组首地址。 偏移量b4很大啊,你有没有硬编码的访问一个数组的这个位置?或者访问一个这么大的结构体的成员?如果有跟这个偏移量对得上的,就算你已经找到这一行代码了! 可能的语句好像不多,例如,写入xarray其中xarray就是那个被破坏的指针;或者,写入p->ii,其中结构体成员ii的偏移量是45个整数大小,而p指针被破坏 本帖最后由 li.wen 于 2014-12-18 23:26 编辑
Impreciserr bus fault指这个错误是由好几个指令周期以前完成的任务造成的,而不是当下一条指令造成的。
如果是当下正在执行的一条指令造成的错误(preciserr),楼主可以通过堆栈什么的找到这个错误。
所以这个错误只能是正向的办法去找了。
即,你看看现在用了那些逻辑功能,一个个注释掉去发现问题的所在;个人觉得这是比较好的办法。
当然,你也可以看看堆栈,有啥提示性的线索。不过个人感觉希望不大。
楼主要坛友协助定位问题,最好还是讲讲做什么功能的。或者贴一些有可能有问题的代码上来。
PS:楼主似乎是参考Joseph Yiu《The Definitive Guide to the ARM Cortex M3》 里面有详细讲到Impreciserr,不过没讲有什么太好的定位问题的办法。 li.wen 发表于 2014-12-18 23:17
Impreciserr bus fault指这个错误是由好几个指令周期以前完成的任务造成的,而不是当下一条指令造成的。
如 ...
这是一个ucos-III的程序,我找到的最后的问题是因为堆栈溢出,堆栈溢出的时候是没事的,后面运行着才有事,我把附件上传上来,你帮忙看下,会的人实在不多,请帮忙下,特别是过程。
Task_Start这个任务堆栈溢出。
溢出语句是图中这个,楼主位说的是开启没有优化的时候测的。
想上传工程可是太大了。我把跑飞的那段代码放上来吧
OS_MSG_QTYOS_MsgQFreeAll (OS_MSG_Q*p_msg_q)
{
OS_MSG *p_msg;
OS_MSG_QTY qty;
qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */
if (p_msg_q->NbrEntries > (OS_MSG_QTY)0) {
p_msg = p_msg_q->InPtr; /* Point to end of message chain */
p_msg->NextPtr = OSMsgPool.NextPtr;
OSMsgPool.NextPtr = p_msg_q->OutPtr; /* Point to beginning of message chain */
OSMsgPool.NbrUsed -= p_msg_q->NbrEntries; /* Update statistics for free list of messages */
OSMsgPool.NbrFree += p_msg_q->NbrEntries;
p_msg_q->NbrEntries = (OS_MSG_QTY)0; /* Flush the message queue */
p_msg_q->NbrEntriesMax= (OS_MSG_QTY)0;
p_msg_q->InPtr = (OS_MSG *)0;
p_msg_q->OutPtr = (OS_MSG *)0;
}
return (qty);
}单独放出来就是下面这句
OSMsgPool.NbrUsed -= p_msg_q->NbrEntries; /* Update statistics for free list of messages */下面是对应的汇编,死在0x0800302C
237: qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */
238: if (p_msg_q->NbrEntries > (OS_MSG_QTY)0) {
239: p_msg = p_msg_q->InPtr; /* Point to end of message chain */
0x08003018 8941 LDRH r1,
231: {
232: OS_MSG *p_msg;
233: OS_MSG_QTY qty;
234:
235:
236:
237: qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */
238: if (p_msg_q->NbrEntries > (OS_MSG_QTY)0) {
239: p_msg = p_msg_q->InPtr; /* Point to end of message chain */
0x0800301A B1B9 CBZ r1,0x0800304C
240: p_msg->NextPtr = OSMsgPool.NextPtr;
0x0800301C 4B52 LDR r3,; @0x08003168
0x0800301E 6802 LDR r2,
0x08003020 F8D3C000LDR r12,
10xjzheng 发表于 2014-12-19 10:31
这是一个ucos-III的程序,我找到的最后的问题是因为堆栈溢出,堆栈溢出的时候是没事的,后面运行着才有事 ...
11楼的li.wen 已经说明了Impreciserr 和 preciserr总线错误的区别。
这是不精确的总线暴力访问异常,CPU无法给出精确的地址。
我觉得楼主不要纠结于这个了
首先楼主既然已经知道堆栈溢出了,那就去fix it。
对于堆栈溢出的话,有可能不会马上die,因为破坏的可能不是关键敏感的,可能不是下面短期内要执行的流程所依赖的。
此时,就不会立即die
而是运行一段时间,莫名其妙的死掉,此时才真正踩到地雷。
但不管怎样立即die,还是延迟die,这些都是要避免的。
你这边的截图
0x 0800 3024,将值存储到 R2所指向的内存,但你注意到了没有,R2的内容为0
这边是正常的吗?
这个问题,要去寻根问底,估计不好弄,CPU也给出不精确的异常报告。
我觉得还不如主动避免,这些莫名其妙的问题。
你说如何?
security 发表于 2014-12-19 11:15
11楼的li.wen 已经说明了Impreciserr 和 preciserr总线错误的区别。
这是不精确的总线暴力访问异常,CPU ...
恩,我觉得可能我深究这个问题可能会学到一些东西。
你说的R2=0,这个可能真的有问题耶,不过为什么不是在这行出问题?
10xjzheng 发表于 2014-12-19 11:43
恩,我觉得可能我深究这个问题可能会学到一些东西。
你说的R2=0,这个可能真的有问题耶,不过为什么不是 ...
其实你已经学到东西了
因为任务栈溢出的话,破坏的东东,你不能预知
任务是否马上die,我们也无法预知
因为这些东西,可能乱七八糟,对于我们而言是这样,对于CPU也是这样
因此,当踩到地雷时,CPU挂掉了,但是CPU自己却给出不精确的异常报告,说明CPU也莫名其妙。
所以要深究,到底哪个是源头,哪个点被破坏了,导致后续的die
还不如去抓罪魁祸首,最初的源头是 栈溢出导致的
这样,也不用费神啊
redroof 发表于 2014-12-18 22:41
可能的语句好像不多,例如,写入xarray其中xarray就是那个被破坏的指针;或者,写入p->ii,其中结构体 ...
大神帮忙看下下面的! 10xjzheng 发表于 2014-12-19 12:01
大神帮忙看下下面的!
因为这是不精确中断,所以你见不到准确的地址,如果你知道是哪个任务的堆栈溢出,直接加大堆栈就行了。
10xjzheng 发表于 2014-12-19 10:31
这是一个ucos-III的程序,我找到的最后的问题是因为堆栈溢出,堆栈溢出的时候是没事的,后面运行着才有事 ...
讲一个可能性,你这个OS_MsgQFreeAll()是你主动调用的吗?
还是系统自动调用的。会不会有可能在你OSMsgFree的时候, 你还有其他进程在送Message过来。或者有处理一半的Message。
我曾经碰到过Message Push太多挂掉的,还有Free完以后还在Push Message导致挂掉的,不过不是在ucos里面碰见的。
定位的办法:
查一下有哪些用户在发送Message(系统发的除外)。然后查一下他们发送的频率。
先全部禁止用户发送,然后再一个个允许发送,排除法。
还有另外一个办法也可以试试:
就是通过IO口来判断执行时序。
例如,
OSMsgFree
{
SetIO1High();
//Do something;
SetIO1Low();
}
OSMsgSend
{
SetIO2High();
//Do something;
SetIO2Low();
}
然后,就是拿示波器器看看两个IO口的关系啦。
说不定就是在IO1高电平的时候,突然IO2也来一个高电平,那就不对了。正常的是两个应该错开的。 li.wen 发表于 2014-12-19 12:57
讲一个可能性,你这个OS_MsgQFreeAll()是你主动调用的吗?
还是系统自动调用的。会不会有可能在你OSMsg ...
不是你说的原因,我的系统才刚刚开始,没有很多东西。 10xjzheng 发表于 2014-12-19 11:43
恩,我觉得可能我深究这个问题可能会学到一些东西。
你说的R2=0,这个可能真的有问题耶,不过为什么不是 ...
R2 = 0,这边是栈溢出导致了逻辑上有问题,但CPU并不认为往这边写东西,有错误。
你如果要去深究的话,那么我建议,你还是从最开始入口
即,从栈溢出开始,一步步跟,看看栈都改写了什么,跟着CPU走
CPU告诉我们,这是个不精确的总线访问异常,手册上也没有见更详细的说明
我想要抓出来,难度系数挺大的
我还是觉得意义不是太大
因为系统代码不一样,栈溢出的时机不一样,破坏的东西不一样,表象也就不一样
但有一点是相同的:这是个要修复的bug。
你项目时间充裕的话,可以继续研究
等待你的结果了,再来教我下~
security 发表于 2014-12-19 13:41
R2 = 0,这边是栈溢出导致了逻辑上有问题,但CPU并不认为往这边写东西,有错误。
你如果要去深究的话, ...
今晚一位大神答应给我调调看,因为我还加了STemwin,我能说堆栈溢出是在GUI_Init中吗,而官方这个函数是没有源码的,汗!!后面我进行把堆栈调大到200后发现,这个函数让堆栈的使用达到了102,而之前我的堆栈大小设置为80 10xjzheng 发表于 2014-12-19 14:17
今晚一位大神答应给我调调看,因为我还加了STemwin,我能说堆栈溢出是在GUI_Init中吗,而官方这个函数是 ...
你的栈,不管是80,还是200
都略显小气了,我想硬件条件应该不至于这么寒碜啊
这么秀气的栈,除非你对栈的需求,非常清晰,才敢设置这么秀气的值
你可以看看,官方的启动代码之类的,基本也不会设置这么小
这么小,会让程序每一步都走得很辛苦~~~ 楼主解决了没有啊 richyhuang 发表于 2015-4-8 11:21
楼主解决了没有啊
不了了之 10xjzheng 发表于 2015-4-9 23:51
不了了之
数据访问违例异常 太烦了,调ucos会经常遇到. richyhuang 发表于 2015-4-10 10:29
数据访问违例异常 太烦了,调ucos会经常遇到.
你把堆栈设置大一点试试 10xjzheng 发表于 2015-4-10 10:51
你把堆栈设置大一点试试
没有用,设10K都不行,就申请了一个semaphore,就不行了,不申请就没事,很奇怪啊。 richyhuang 发表于 2015-4-12 23:14
没有用,设10K都不行,就申请了一个semaphore,就不行了,不申请就没事,很奇怪啊。 ...
create了没有啊?
页:
[1]