搜索
bottom↓
回复: 49

慎用AVR Studio 4.18,有不完善之处(详见6楼)

[复制链接]

出0入0汤圆

发表于 2009-12-18 18:22:31 | 显示全部楼层 |阅读模式
如果C文件函数里的参数与其对应的头文件里描述得不一样,则会导致参数传递不成功,但函数照常执行。编译时,不会给出提示。
举个例子,a.c和a.h。
a.c:
void abc(unsigned char x)
{
……
}
a.h:
void abc(unsigned long x);
abc()里的语句会照常执行,但x永远是0。编译环境:AVR Studio 4.18、WinAVR 20090313、ATmega168。

我记得4.17是绝对会提示的。
发现这个漏洞的来响应一下。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2009-12-18 18:41:00 | 显示全部楼层
刚刚装了SP1,版本变成Build 692,问题依旧。

出0入0汤圆

发表于 2009-12-18 18:42:51 | 显示全部楼层
你不会是关了warning吧?
再说了,这有问题也是winavr的事,关avrstudio什么事?

出0入0汤圆

 楼主| 发表于 2009-12-18 19:10:12 | 显示全部楼层
回2楼,我一直用WinAVR 20090313。在换成4.18前,从未遇到过这种情况。
警告能关掉吗?请问怎么关?

出0入0汤圆

发表于 2009-12-18 19:51:44 | 显示全部楼层
楼主吧工程上传上来看看。

出0入0汤圆

 楼主| 发表于 2009-12-18 20:09:40 | 显示全部楼层
点击此处下载 ourdev_516329.rar(文件大小:15K) (原文件名:1.rar)

工程在此,请大侠们验证。
拿串口观察。若不改动a.h,则显示00。若把a.h的“void a(unsigned long x);”改为“void a(unsigned char x);”,则正常。
USART.c是串口的驱动,用其它型号的话,换成自己的就行。

出0入0汤圆

发表于 2009-12-18 20:34:00 | 显示全部楼层
因为AVR一个寄存器不够LONG这么宽.....
以long传进去 函数得到的只是最高字节(同时可猜:avr-gcc传递参数时高字节在低号寄存器)
如果你在a.c里面include a.h是会有警告的

如果在32位机上面 这样做不会出错(前提是:参数范围在0~0xFF)

漏洞在你自己 和前几天那个函数不写return而无视警告却怪运行正确的人有得一比.

(以上内容仅是猜测 本人不负责)

出0入0汤圆

 楼主| 发表于 2009-12-18 20:50:34 | 显示全部楼层
回6楼,不在a.c里面包含a.h里,的确不会产生警告。包含了,那肯定是有警告的。我承认我疏忽了这一点。
但是这样一来,一个C文件对应一个头文件就没有意义了。反正两个定义可以不一样,乱写它也不会提示。
打个生动的比方,主函数去商店买东西,头文件说这个函数是两斤重的。结果从仓库里提了货,一称,只有半斤。每次都要仓库监督着头文件,岂不是很累?

出0入296汤圆

发表于 2009-12-18 21:00:38 | 显示全部楼层
LS你终于理解到了
C语言本身就允许欺骗的……

我就经常利用这个特性……
为了屏蔽某些内容,我经常给不同的“客户”——也就是别的.c模块,不同的.h……

类型……大小……XXXX都可以骗得……

出0入0汤圆

发表于 2009-12-18 21:02:21 | 显示全部楼层
"在a.c里面include a.h"

是非必要的部分
理论上
a.c要不要写一个a.h也是非必要部分

但不管如何 写一个正确无误的程序是你要做的

出0入0汤圆

 楼主| 发表于 2009-12-18 21:04:37 | 显示全部楼层
谢谢楼上各位大侠,以后一定多加注意。
问8楼,比如说呢?可以拿来干吗?

出0入0汤圆

 楼主| 发表于 2009-12-18 21:06:02 | 显示全部楼层
【9楼】 aozima
但不管如何 写一个正确无误的程序是你要做的
-----------------------------------------
说得对。以前一直没出现过不包含的情况。这次真的是大意了。

出0入296汤圆

发表于 2009-12-18 21:16:19 | 显示全部楼层
比如,你这个.c里面有一个结构题,这个结构体里面保存了很重要的数据,
按道理只能由这个.c来处理。
但是,你的这个模块,团队里面的其他人也要用,于是,你就需要给他们一个.h文件,和.a文件。
问题在于,.h文件里面必须要包含着个结构体,否则别人无法使用你这个模块,比如,有一个初始化
函数,根据用户的基本输入,初始化,返回一个这样的结构体;还有一些函数需要以这个结构体作为
输入参数。你要注意,尽管用户不需要知道结构体的内容,也不应该自己访问结构体的成员变量,但
是它至少是一个比不可少的类型,用来在函数之间传入传出……
可怕的事情发生在不知情的同事有一天发现,直接修改结构体变量的某个成员很方便就能实现某个功能……
灾难由此开始……你的库函数被绕开了,最关键的是,某些被隐藏在.a里面的操作也被绕开了……于是
原本天衣无缝的逻辑被撕扯了……

如何防止别人直接访问结构体?当然是让结构体变成板转啦!比如:看下面的例子

typedef struct
{
    unsigned char StructMask[sizeof(
        struct _
        {
            ...这里填放原来这个结构体应该有的内容
        })];
}NAME;

是不是很贼啊?
这种技术叫做掩码结构体

出0入0汤圆

发表于 2009-12-18 21:20:55 | 显示全部楼层
"以前一直没出现过不包含的情况"能不包含的情况下尽量不包含

出0入0汤圆

 楼主| 发表于 2009-12-18 21:23:59 | 显示全部楼层
大体上明白,改天实践一下。

出0入0汤圆

 楼主| 发表于 2009-12-18 21:25:24 | 显示全部楼层
【13楼】 aozima
能不包含的情况下尽量不包含
---------------------------
包含了,不是利大于弊吗?

出0入0汤圆

发表于 2009-12-18 21:28:46 | 显示全部楼层
这个帖子因傻孩子的回复而精彩,书上看不到的用法呀。

出0入0汤圆

发表于 2009-12-18 21:43:41 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-18 21:51:44 | 显示全部楼层
傻孩子太COOL了,但愿能早日见到你的《AVR32 UC3工程师快入门指南》

出0入0汤圆

发表于 2009-12-19 09:07:11 | 显示全部楼层
你要注意,尽管用户不需要知道结构体的内容,也不应该自己访问结构体的成员变量,但
是它至少是一个比不可少的类型,用来在函数之间传入传出……
----------------------------------------------------------------------------------

如果不想别人知道你结构体类容,直接把结构体定义到C文件里(或者一个单独的头文件,只给自己用,不公开)
公开的头文件传递指针全部用 void *指针。

如果需要用户定义结构体变量,在公开的头文件全部定义成数组,用户只要传递数组名就行了。
用户的感觉是完全不涉及结构体,没有任何形似的结构体和结构体操作,
传递指针全部用void *指针。至于void *指针的具体含义,是有你的函数来解释的,这部分函数做成库文件,
对方也看不到的。


我的ID是voidx(void *),在C语言里最喜欢用的就是void *指针了。
(当一个指针不指向任何类型,换句话,也可以说,这个指针指向任意类型)

出0入0汤圆

发表于 2009-12-19 10:09:02 | 显示全部楼层
楼上的方法才是正道!

出0入0汤圆

发表于 2009-12-19 11:17:34 | 显示全部楼层
傻孩子的方法,可以有效拒绝接修改结构体变量,但是自己用起来肯定也很头大。19L 才是正道,个人也很喜欢 void *,不指向任何类型,同时可以指向任何类型。

出0入85汤圆

发表于 2009-12-19 12:34:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-19 12:50:14 | 显示全部楼层
bj

出0入0汤圆

发表于 2009-12-19 15:12:47 | 显示全部楼层
上官大侠能不能给你实例看看,谢谢

出0入296汤圆

发表于 2009-12-19 16:01:25 | 显示全部楼层
to 【19楼】 voidx void *
    此方法太危险。我这么做的好处是,给别人一个基本的安全信息:
    在C语言中安全的处理数据起码需要两个基本元素:
    1、起始地址
    2、大小

    如果这两个信息编译器都能在编译时刻验证和检测,那么可以避免很多潜在的问题。
    如果把这两个信息中的大小抹去(由使用者和客户人为约定,而不使用技术上的约束),代码本身
就是拥有风险的。我把这类代码称为“信用代码”。
    void *是不能sizeof的……

关于掩码结构体,可以用下面的宏来实现

# define MASKED_STRUCT(__CONTENT)\
            struct\
            {\
                unsigned char MaskStruct[sizeof(struct _{__CONTENT})];\
            }

使用的时候和typedef 一起用,比如
typedef MASKED_STRUCT
(    //注意这里是圆括号
    ...这里填写结构体的内容
) EXMPLE_TYPE_NAME;


还有,如果我觉得某个代码结构用起来复杂,我一定会编写对应的宏的……这就是为什么我的
代码里面那么多宏……

to 【21楼】 windy__xp 龙啸
     忘记说了…….c里面有一个没有mask过的结构体,这个.c是不会去包含那个欺骗后的.h的。

出0入0汤圆

发表于 2009-12-19 16:13:53 | 显示全部楼层
太强大了   COOL呢

出0入0汤圆

发表于 2009-12-19 17:48:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-19 18:59:07 | 显示全部楼层
【25楼】 Gorgon Meducer 傻孩子
------------------------------
    学习了,C的确太灵活了。

    同时由于C的灵活,稍微不注意,就会带来一些意想不到的错误,从这一点上来说,还是感觉汇编驾驭起来更“踏实”,虽然麻烦,^_^

    说个最近遇到的事,最近移植uCOS II 到XMEGA,虽然移植函数写完了,后来发现实际应用不太方便,于是自己写了个简单的时间片轮转调度的核,时间片定时中断用 naked 申明不保护现场,如下:
    void TCC0_OVF_INT( void ) __attribute__ ( ( signal, naked ) );

    ISR( TCC0_OVF_INT )
    {
        asm volatile(" PUSH R0 " );    // 时间片中断,系统任务调度,保存所有的寄存器
        ……
        asm volatile(" POP  R0 " );
    }

    后来调试,任务调度总是有问题,后来看汇编代码,发现 TCC0 中断没有返回,后来查资料才知道 这个“裸体”实在太彻底了,需要人工加入 reti 指令,如下:

    ISR( TCC0_OVF_INT )
    {
        asm volatile(" PUSH R0 " );    // 时间片中断,系统任务调度,保存所有的寄存器
        ……
        asm volatile(" POP  R0 " );
        asm volatile(" RETI    " );
    }

出0入0汤圆

发表于 2009-12-19 19:44:02 | 显示全部楼层
刚下了studio418,受教了。

出0入0汤圆

发表于 2009-12-19 19:48:52 | 显示全部楼层
想裸奔那你就得自己手工加reti

出0入0汤圆

发表于 2009-12-19 20:30:00 | 显示全部楼层
如果结构体的内容,不让客户知道,那就不存在客户调用传递或返回这种结构体了!

出0入0汤圆

发表于 2009-12-19 21:07:41 | 显示全部楼层
gcc裸中断保护现场,还需要把R1清零。

出0入0汤圆

发表于 2009-12-19 21:28:53 | 显示全部楼层
32L 什么意思?

出0入0汤圆

发表于 2009-12-24 15:03:04 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-7-8 16:51:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-8 17:26:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-8 22:19:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-22 18:52:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-22 22:31:33 | 显示全部楼层
学习。

出0入0汤圆

发表于 2011-7-10 12:34:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-25 19:53:39 | 显示全部楼层
都是高手呀

出0入0汤圆

发表于 2011-8-25 22:33:30 | 显示全部楼层
觉得还是GCC比较好用

出65入0汤圆

发表于 2011-8-28 22:22:53 | 显示全部楼层
mark 结构体掩码

出0入0汤圆

发表于 2011-11-17 21:58:42 | 显示全部楼层
太强大了!!!

出0入0汤圆

发表于 2011-12-13 17:22:58 | 显示全部楼层
厉害,刚安装了avr studio 4.18

出0入0汤圆

发表于 2012-2-21 11:29:52 | 显示全部楼层
太强大了,看得云里雾里的,不知所云!~

出0入0汤圆

发表于 2012-5-9 17:17:36 | 显示全部楼层
飘过。。。。。。。。。。。。。。。

出0入0汤圆

发表于 2012-10-7 19:16:11 | 显示全部楼层
帖子不错!大家回复的都很精彩!谢谢,受用了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 03:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表