今天在写代码的时候,遇到一个奇怪的问题,在函数内定义局部变量数组,如果这个数组较大时程序就会跑飞,跑飞的地方如下:
/*这一块是跑飞的代码*/
uint32_t UserCode[244];
UserCode[0]=1;
/*代码over*/
如果数组比较小的话就没有问题,然后我上网查了一下资料这里理一下:
1、由于局部变量创建的时候是静态创建在栈上的,所以栈的大小限制了局部变量的size,如果栈小了,在运行的时候就会出现溢出,程序当然就飞了。这里就有概念上的疑问了:静态创建和动态创建区别是什么?局部变量占用的是栈的空间,那么其他类型的变量呢?下面我们就来看这个问题。
2、静态创建和动态创建的区别
我个人的理解:静态创建分为两个部分,一个是编译时,这个时候我们定义的静态变量和全局变量将在自动划分内存空间;一个是在运行时,就是局部变量,在栈区生成一个固定大小的空间;为什么说他是静态的呢?因为这些变量或数组空间的大小我们是预先可知的。而动态创建呢?我们使用malloc和free创建和释放内存空间,他们的大小是按需分配,所以是动态创建,是在堆上分配的。
3、变量类型分为:局部变量,静态局部变量,全局变量,静态全局变量。他们在存储上可以根据创建的方式进行分析,静态和全局都是在编译是进行创建的,所以是在普通的内存区域,局部变量是在运行时创建的,在栈上,但是栈上的空间和普通内存区域有没有重复呢?这个目前我还不清楚,还需要继续加深理解。在作用域上:局部变量在调用函数的时候创建,返回的时候系统自己进行销毁;全局变量可以在工程的所有单元文件下使用;静态全局变量只能在当前单元文件下使用;静态局部变量,只创建一次,函数返回的时候不对他进行任何操作,所以下次进函数的时候他保留的是上一次的值,不会清除。
4、堆和栈的区别:堆用于动态分配空间等,由程序员创建和操作;栈是由编译器自动分配的,主要用于存放函数的参数值和局部变量。平时说的函数调用或中断入栈等等都是指的这里编译器分配的栈。
好,现在我们回到刚刚的出现问题的代码上来,然后我们看看怎么解决,由于分析出是栈不够的情况,所以我们就可以通过其他两种方式解决:
1、改变变量数组类型:全局或静态的,这样由编译器分配内存
2、使用malloc动态分配空间:由于malloc不占用栈区,所以也可以我们先改为全局变量试试
关键字:arm 程序 变量
引用地址:
arm学习笔记--程序中变量引起的思考
推荐阅读最新更新时间:2024-03-16 15:00
对嵌入式底层开发学习的一点看法
简介:不知不觉中,学习嵌入式已经有差不多两年的时间了,从大二的时候开始学习 DSP ,现到开始接触 ARM9 ,有很大的感触,所以分享出来,和大家一起进步。首先说明,这些只是个人学习中的看法,如果你与我的看法不同,那么请把你的看法分享出来。让大家也进行一下学习。 在老师的要求下。把 51 单片机着为入门嵌入式的接触 MCU ,现在想起来,老师做得很对,因为他当时要求我在两个月的时间内把 51 开发板板上的接口驱动都写出来,但是,不要求我把 51 搞太长的时间。只要知道怎么进行控制外设,但是有一点。 UART , IIC , SPI 等常见的驱动程序设计必须了解其真正的原理。这为后来的学习打下了强有力的基础。 在大二的暑假,
[单片机]
ARM笔记: 常用ARM汇编指令
(1)b,bl:相对跳转指令。可跳转范围是当前指令的前后32MB。 (2)mov,ldr,str:mov比较熟悉,就是赋值。ldr本意为“大范围的地址读取伪指令”。str为存储指令。 COUNT EQU 0x40003100 …… LDR R1,=COUNT MOV R0,#0 STR R0, COUNT是一个数值,为0x40003100。 LDR R1,=COUNT是读取COUNT的值并赋值给R1,即R1存放的是地址0x40003100. MOV R0,#0是将立即数0放到R0中。 STR R0, 是一个典型的存储指令,将R0中的值放到以R1中的值为地址的存储单元去。实际就是将0放到地址为0x400
[单片机]
ADC0809转换程序
程序框图 电路 程序 ORG 05A0H 05A0 758153 SE11: MOV SP,#53H 05A3 757E00 MOV 7EH,#00H 05A6 757D08 MOV 7DH,#08H 05A9 757C00 MOV 7CH,#00H 05AC 757B09 MOV 7BH,#09H 05AF 757A10 MOV 7AH,#10H 05B2 757910 MOV 79H,#10H ;显示缓冲区初值 05B5 120425 LO18: LCALL DIS
[单片机]
MSP430F5529单片机程序整理(串口、AD、定时器等)
#include msp430.h #include stdint.h #include uart.h #include Flash.h #include ad.h #include stdio.h #include string.h #define CPU_F ((double)1000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/
[单片机]
ARM7单片机(学习ing)—(四)、定时器—02
只要知道了Startup.s中对单片机时钟的定义~~ 也就是这句话:当外部晶振频率为12MHz时,系统时钟60MHz,外设时钟15MHz~~ 无敌了~~ 感觉一下子好学了好多~~ 不过我还是有点不太清楚就是外设时钟?为什么是15MHz~~ 现在可以先留着~~慢慢来吧~~ 四、定时器 四—(02)、定时控制LED闪烁(应用查询法~~) MDK4_1.c //------------------------------------------------------------------------------ //使用定时器0实现1s定时,控制LED闪烁 //今天使用的是查询法~~ #include lpc210x.
[单片机]
学习51单片机必写的几个程序
51单片机偶完全自学的,因为想学的时候离学校开课还早得很。 学完了单片机,现在学校课也开完了,收获很大。现将偶学习经验写出来,供大家交流。 1、因为有了C语言和汇编语言的基础,加上模电学得不错。微机原理也上了。所以我只花了半天的时间把51的引脚功能和内部结构搞清楚了。偶认为学51重要的就是搞清内部结构和地址空间。 2、仅用了几个小时简单看了一下51的汇编指令和C语法。 我个人认为学习程序语言的语法规则是很简单的,且各种语言之间都有共通的地方,有了汇编和某种高级语言的基础学其它语言应该能很快上手。 3、直接编程练习,软件硬件实现。 我的第一个程序是跑马灯程序。 这个会让你熟悉端口的用法,普通流程控制。当然是C语言写一个,汇
[单片机]
ARM汇编伪指令介绍之二
1、 AREA 语法格式: AREA 段名 属性 1 ,属性 2 , AREA 伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用 | 括起来,如 |1_test| 。 属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下: CODE 属性:用于定义代码段,默认为 READONLY 。 DATA 属性:用于定义数据段,默认为 READWRITE 。 READONLY 属性:指定本段为只读,代码段默认为 READONLY 。 READWRITE 属性:指定本段为可读可写,数据段的默认属性为 READWRITE
[单片机]
基于ARM的油田单井油罐太阳能加温控制器的设计
油田中的采油系统分布相对较为稀疏,油罐储存和传输过程中需要对油温进行加热,以避免因原油凝固而不能传送到中间站进行处理。由于每个井口的分布位置相对较远,因此需要对每个单独的油罐进行加温控制。目前所使用的加温装置大多是以伴生气为燃料的水套炉或者以电能为能源的电加热器等 。水套炉存在热效率低、能耗高、炉体易产生烧蚀损坏、维修维护成本高等弊端,而且,伴生气燃烧过程中所排放的废气对环境造成污染。电加热器存在耗电高、易停电、频繁扫管、造价高等弊端。本文提出了一套以太阳能集热器为主、热泵热水器为辅助热能提供装置、ARM为主要控制器的加热系统 。热泵与太阳能集热设备、蓄热机构相联接的系统方式, 不仅能够有效克服太阳能本身所具有的稀薄性和间歇性
[单片机]