打印

使用局部变量还是使用全局静态变量的问题

[复制链接]
5220|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gdmgb520|  楼主 | 2011-8-20 09:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我用的MSP430F2471 ,4KRAM,在通信时需要使用一个320B的缓冲,这个缓冲只是在同事时用来打包、发送的缓冲。
请问大家,这个缓冲是使用局部变量(在函数内部定义),还是使用全局变量?那种方式比较好。
使用全局变量,这就意味着有320B的内存空间始终被占用。而使用局部变量,栈空间是否够用?(现在使用的是局部变量,程序跑起来是没有什么问题的。)另外,每次调用该函数,MCU要重新分配一片320B 的内存空间给该函数,是否会占用较多的MCU时间,是否会对MCU造成负担?MCU在分配临时变量时是怎样的工作机制?

请大家就以上问题分析下,谢谢!

相关帖子

沙发
gdmgb520|  楼主 | 2011-8-20 09:36 | 只看该作者
自己顶一个。

使用特权

评论回复
板凳
NE5532| | 2011-8-20 09:40 | 只看该作者
纠正一下,MCU不会分配变量空间,这个是编译器干的。到底用哪种变量类型完全取决于你的应用需求,局部静态变量和全局变量占用的资源理论上是一样的,指示局部静态变量在外部不能被引用而已。

使用特权

评论回复
地板
原野之狼| | 2011-8-20 10:17 | 只看该作者
我用的MSP430F2471 ,4KRAM,在通信时需要使用一个320B的缓冲,这个缓冲只是在同事时用来打包、发送的缓冲。
请问大家,这个缓冲是使用局部变量(在函数内部定义),还是使用全局变量?那种方式比较好。
A:无好坏之分,看应用要求。如果作用域需要全局的就定义全局变量,否则就定义局部变量。
使用全局变量,这就意味着有320B的内存空间始终被占用。而使用局部变量,栈空间是否够用?(现在使用的是局部变量,程序跑起来是没有什么问题的。)
A:栈空间由程序初始代码确定或由编译器确定,够不够用需要根据程序执行过程大概估算。
另外,每次调用该函数,MCU要重新分配一片320B 的内存空间给该函数,是否会占用较多的MCU时间,是否会对MCU造成负担?MCU在分配临时变量时是怎样的工作机制?
A:此分配在编译时确定,并不是动态内存分配,无所谓负担。至于其机制,你从汇编级跟踪一下就知道了,这也能帮助你看看到底带来了什么负担。

使用特权

评论回复
5
yewuyi| | 2011-8-20 11:37 | 只看该作者
一般通信所需要用到缓冲空间都定义为全局变量

使用特权

评论回复
6
gdmgb520|  楼主 | 2011-8-20 11:54 | 只看该作者
4# 原野之狼

谢谢。
不仅仅是给出了解决问题的方向,更给出了思考方式。
没想到,经你已回复,我的提问也变得调理清晰了。


u8 ParkPacketBuf[10][32] = {{0},{0}};   // 定义发送缓冲
//反汇编代码。开来在初始化变量时MCU做了一些事情,清空内存区域。
00870C    410C               mov.w   SP,R12
00870E    523C               add.w   #0x8,R12
008710    403E 0140          mov.w   #0x140,R14
008714    12B0 A900          call    #?ClearMemoryBytes

另外,再请教大家,我用的IAR EW430,怎样看堆栈大小啊,我看了map文件,里面没有。

谢谢

使用特权

评论回复
7
gdmgb520|  楼主 | 2011-8-20 13:39 | 只看该作者
5# yewuyi

收到!

使用特权

评论回复
8
gdmgb520|  楼主 | 2011-8-20 15:23 | 只看该作者
从上面的汇编看,是想把缓存分配在堆栈里。
所以这样的定义肯定是不对了。
放到函数外定义,全局变量。

使用特权

评论回复
9
Breming| | 2011-8-20 15:44 | 只看该作者
飘过。。。。。。。。。。。。

使用特权

评论回复
10
misra| | 2011-8-20 15:56 | 只看该作者
5# yewuyi
有哲理。
我也这样用。却没想到你这样的理论高度啊  牛啊

使用特权

评论回复
11
yewuyi| | 2011-8-20 20:41 | 只看该作者
在项目编译设置中设置一下,一般都能应该能在MAP中生成栈开销的信息的把

使用特权

评论回复
12
yewuyi| | 2011-8-20 20:43 | 只看该作者
不过,写代码的人,应该牢牢记得代码的资源开销,如果只是顺着手感一味写下去,则多数都是要吃苦果子的.

如果你能牢牢记得资源开销,则用了多少栈空间,即使不看MAP也是小葱拌豆腐,一清二楚

使用特权

评论回复
13
gdmgb520|  楼主 | 2011-8-20 20:56 | 只看该作者
12# yewuyi

哎,还要努力。我看了下反汇编,有些变了是分配在寄存器里的,有些变量是分配在栈空间的。不知道他们是怎样的规律。
另外,调用函数也是要栈空间的,今天看了IAR的帮助文档,还没太搞明白。

通过设置IAR编译器,确实是输出了函数的栈使用情况,只是我还看不太明白。

使用特权

评论回复
14
ahgao| | 2011-8-20 21:39 | 只看该作者
堆栈的分配和使用在不同软硬件平台上是不一样的。IAR+MSP430没有用过。不过就我用过的几个平台上来说,栈空间也是需要预定义大小的,也就是说即使是定义为局部变量,也不见得能有效节约内存,而且带来了栈溢出的风险。楼主想要动态分配大内存区其实是很基本的应用。C中用malloc,C++用new。

使用特权

评论回复
15
goto0514| | 2011-8-20 22:11 | 只看该作者
全局的好,局部不建议用,老手可以用局部。

使用特权

评论回复
16
原野之狼| | 2011-8-20 23:50 | 只看该作者
对于单一栈的平台,比如51,AVR,一般栈的指针是由系统自带的启动代码初始化的,当然你也可以手动修改这段代码。
系统的RAM空间,减去全局变量后,剩下的都归为堆和栈使用,其范围由编译器自动定界,编译器会输出一些系统宏来描述这些边界。
堆和栈向不同的方向生长,一般栈位于高地址,向低地址空间延伸,堆则反之。
其二者并不划分三八线,因此存在打架的可能。

对于多栈的平台,比如ARM,Cortex,各栈区的起始地址和大小都得显式地指定,如果需要启用堆,那么堆起始也得显式地指定。以上各分区同样存在打架的可能。

教科书讲局部变量位于栈中,倒是没错,但是却容易误导人。因为实际上,局部变量很有可能不在栈中,而是在寄存器中,因为位于寄存器中可以加快访问速度。于是有人可能会问,位于寄存器中岂不是会对重入造成影响?其实不是的,至于原因嘛,看看每个函数编译后的汇编级代码里头几条指令做了什么就知道了。那就是PUSH指令,也就是说如果有必要,局部变量是会在下一级函数中被压入栈的,所以才说教科书的说法没有错,但是没有讲明确。当寄存器不足以容纳局部变量的时候,局部变量才会被实实在在的位于栈中。

以上说的有个特例,那就是KEIL的做法,KEIL的优化非常厉害,当然其厉害也是需要付出代价的。如果你记得的话应该知道在keil里有个call tree的概念,这个东东是用来干嘛的?它是用来跟踪程序执行流程的,在编译时keil就已经明确知道了call tree,所以只要可行它就会把局部变量直接放在寄存器中,这个做法不同于刚刚说的做法,因为它不会做压栈保护,当然我加了限定词“只要可行”,也就是并不是所有的局部变量都这样干。现在我们知道代价是什么了,代价就是只要破坏了call tree,系统就有可能崩溃,谁会破坏call tree呢?重入以及函数指针。在这种情况下就需要采用特别的技术来修正这个问题了,否则会死得很惨。

使用特权

评论回复
评分
参与人数 2威望 +2 收起 理由
gdmgb520 + 1 谢谢
ahgao + 1
17
gdmgb520|  楼主 | 2011-8-25 22:37 | 只看该作者
16# 原野之狼

谢谢讲解。有些现在还理解的不是很清楚,有些已经搞明白了。
IAR确实把有些变量放到了寄存器中,而有些变量(如32位的长整型)则放到了栈空间。定义的数组也一股脑的放在了栈空间,运行没有出问题是因为我的内存富余比较多,但幸亏我注意到了这个问题。

谢谢大家 的讲解与讨论。

使用特权

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

本版积分规则

个人签名:了解新东西才知道自己的不足。 www.elecbench.com

67

主题

452

帖子

1

粉丝