打印

死循环

[复制链接]
1495|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
司徒老鹰|  楼主 | 2011-10-22 08:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近正在做以太网协议和UCOS的整合工作,发现一个问题,导致发生了硬件错误,即进行死循环,最后的问题已经解决,我抽象描述如下:

OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
在调用OSSemPend,我传递err参数的时候使用了两种方法:
INT8U *err
OSSemPend (..., err);
其中函数执行一切正常,但是return的时候发生了错误;
原因:IAR使用了R4寄存器进行传递参数err,R4的值为0x2A,err的value也是0x2A,因此err在函数中改变了地址0x2A所指向的值,由于这个地址不能被这样访问,因此错误;


INT8U err;
OSSemPend(..., &err);系统运行正常,没有任何错误;
IAR没有使用寄存器传递参数,而是使用了RAM,内存传递一切正常

我使用第一种方法应该是没有问题的,而IAR却错误处理了,这个有什么原因吗?
沙发
llljh| | 2011-10-22 08:39 | 只看该作者
第一种方法不能说没有问题。OSSemPend里使用参数err是这样使用的:
        *perr = OS_ERR_PEVENT_NULL;
传递的参数虽然是指针,但改变的确是指针所指向的内存单元的值。在任务里定义的局部变量其初始值是不确定的, 即INT8U *err;  err的值是个不确定的值,没准指向的是哪个内存单元了,这样使用当然会意外改写其它位置的数据。
   
     第二种方法没有问题,第一种方法如果改一下也应该没有问题。在任务里定义:
    INT8U temp[5];
      INT8U *err;
      err = &temp[0];
      OSSemPend (..., err);
      前提是temp[0]这个变量在此任务中没有其它用途。

使用特权

评论回复
板凳
supernan| | 2011-10-22 08:42 | 只看该作者
INT8U *err
OSSemPend (..., err);
-----------------------------------
典型的错误使用指针。
指针errp在没有赋值初值的时候,禁止*err写操作。
楼主的这段代码,按理说,编译器应该会有警告。

使用特权

评论回复
地板
zwll| | 2011-10-22 08:46 | 只看该作者
野指针你也敢当参数传递?勇气可嘉啊!

使用特权

评论回复
5
juventus9554| | 2011-10-22 08:59 | 只看该作者
没有赋值的指针就引用,编译器应该会给你警告的

使用特权

评论回复
6
pengf| | 2011-10-22 09:03 | 只看该作者
第一种方法确实是错误的使用了指针

使用特权

评论回复
7
司徒老鹰|  楼主 | 2011-10-22 09:06 | 只看该作者
定义每个变量,尤其是指针变量需要进行初始化,我在这里疏忽了,谢谢!

若进行以下方式
INT8U *err = NULL;    //程序仍然会进入异常程序,是不是NULL不是关键;
原因还是一样的 R4存储了err的指针变量,此句的含义是将err的value转成了0,即将R4寄存器的值变成了0,那么程序内部的操作就操作了0x0000地址,肯定是错误的;

另外安全的方式,就是在堆上使用malloc分配一块内存,然后将其地址赋值给err,这个方式和使用
INT8U err, 取err的地址方式是一样的,区别只是地址变量的生命周期不同而已;

因此使用指针进行函数的传递,一定是要指向一块合法内存(可以取变量的地址,或从堆上分配),否则调用都会导致问题。
我的问题还是错误地使用了指针,IAR还是正确的。

使用特权

评论回复
8
renyaq| | 2011-10-22 09:12 | 只看该作者
指针必须指向有效的内存单元(可以指向某个变量、数组、堆),你才能往里写东西!

使用特权

评论回复
9
司徒老鹰|  楼主 | 2011-10-22 09:16 | 只看该作者
嗯,了解了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

427

主题

3735

帖子

8

粉丝