STM32内存五区及堆栈空间大小设置(启动文件浅析)

发布于:2025-03-01 ⋅ 阅读:(13) ⋅ 点赞:(0)

前言

嘿,朋友们!今天咱们来聊聊STM32的内存五区和堆栈空间大小设置。这可是嵌入式开发里的“必修课”,要是没整明白,程序说不定就“翻车”了。别担心,我这就带你一步步搞懂这事儿,让你轻松上手,稳稳地写出靠谱的代码!准备好了吗?Let's go!


一. 内存五区的概念

在嵌入式系统中,堆(Heap)和栈(Stack)是两种不同的内存区域,它们在程序运行中扮演着重要的角色。除此之外,还有其他几个关键的内存区域,包括全局区/静态区、常量区和代码区(内存五区

1.1 栈(Stack)

栈是由编译器自动管理的内存区域,用于存储函数调用时的参数、局部变量等。栈的大小在系统启动时确定,如果栈空间过小,可能会导致栈溢出,进而引发程序崩溃,所以选定合适的栈空间是的很有必要的。栈的特点是后进先出(LIFO),即最后进入的元素最先被移除。

#include <stdio.h>

//在C语言中,栈内存用于存储函数调用时的局部变量
void StackExample() 
{
    int localArray[10]; // 在栈上分配一个大小为10的数组
    int size = 10;

    // 使用栈上的内存
    for (int i = 0; i < size; i++) 
    {
        localArray[i] = i * i; // 栈内存存储平方值
    }

    // 打印栈上的内存内容
    for (int i = 0; i < size; i++) 
    {
        printf("localArray[%d] = %d\n", i, localArray[i]);
    }
}

1.2 堆(Heap)

堆用于动态内存分配,由程序员自主通过mallocfree函数管理分配。堆的大小通常是动态的,由剩余的可用内存决定。堆的特点是灵活,可以动态分配和释放内存,但如果不正确管理,可能会导致内存泄漏。

注:用户不能通过malloc指定地址去申请内存,可能会导致内存碎片化或其他问题,能指定申请内存的大小

#include <stdio.h>
#include <stdlib.h>

//堆内存通常用于自主动态分配内存
void HeapExample() 
{
    int *array;// 定义一个指向整数的指针,用于存储动态分配的数组
    int size = 10; // 需要分配的数组大小

    // 从堆中分配内存,分配的总字节数为40字节,array得到的是一个指向分配内存的指针
    array = (int *)malloc(size * sizeof(int));
    //检查malloc是否成功分配内存。如果分配失败,malloc会返回NULL。
    if (array == NULL) 
    {
        printf("Memory allocation failed!\n");
        return;
    }

    // 使用分配的内存
    for (int i = 0; i < size; i++) 
    {
        array[i] = i * i; // 示例:存储平方值
    }

    // 打印分配的内存内容
    for (int i = 0; i < size; i++) 
    {
        printf("array[%d] = %d\n", i, array[i]);
    }

    // 释放分配的内存
    free(array);
    printf("Memory freed.\n");
}

1.3 全局区/静态区

全局区/静态区用于存储全局变量和静态变量。它分为两个部分:

  • .bss段用于存储未初始化或初始化为0的全局变量和静态变量。它不占用可执行文件的空间。

  • .data段用于存储经过初始化且初始化值非0的全局变量和静态变量。

#include <stdio.h>

// 全局变量
int globalVar = 42;

void StaticExample() 
{
    // 静态变量
    static int staticVar = 0;

    // 每次调用函数时,静态变量的值会保留,不会像局部变量一样消失
    staticVar++;
    printf("Global Variable: %d\n", globalVar);
    printf("Static Variable: %d\n", staticVar);
}

1.4 常量区

常量区用于存储字符串常量和其他不可修改的数据。这些数据在程序运行期间是只读的

const char *message = "Hello, World!";

1.5 代码区

代码区用于存储程序的执行代码,包括函数和中断向量表等。

Flash存储器用于存储程序代码和常量数据,而RAM用于存储变量(全局变量、静态变量和局部变量)和堆栈等运行时数据。

存储器类型 地址范围 用途
Flash存储器 0x08000000 - 0x080FFFFF 程序代码、中断向量表、常量数据
RAM存储器 0x20000000 - 0x2000FFFF 全局变量、静态变量、堆栈、堆

二. 设置堆栈大小的方法

在使用STM32编程时,一般情况下我们编写程序很少出现栈溢出所以不会关注堆栈空间的大小,而在STM32的启动文件中,已经帮我们预先设置好了堆栈空间的大小。如下图所示的启动代码中,Stack栈的大小为:0x400(1024Byte),Heap堆的大小为:0x200(512Byte)。

在STM32工程中,有两种主要方法可以设置堆栈大小:

方法1:直接在启动文件中修改

启动文件(通常是startup_stm32xxxxx.s)中包含了堆栈大小的设置。可以直接修改这些值来调整堆栈大小:

方法2:可以通过图形界面配置堆栈大小

打开启动文件,点击下方Configuration Wizard,点expand all展开,可在value栏框中设置堆栈空间的大小。

总结

今天的内容就到这里啦!咱们一起把STM32的内存五区和堆栈空间大小设置给“拿下”了。内存五区就像是程序的“小家”,每个区域都有自己的“职责”,把它们安排得明明白白,程序才能跑得顺顺当当。至于堆栈空间大小设置,那更是关键中的关键,要是堆栈给少了,程序一“激动”就容易“爆仓”,要是给多了,又有点浪费。所以,根据自己的需求,合理地在启动文件里调整一下,就能让程序舒舒服服地运行啦。

希望今天的分享对你有帮助哦!要是还有啥疑问,或者想继续唠唠嵌入式开发那些事儿,随时来找我哈。下次见啦,拜拜!