计算机中的代码内存分布位置

其实在之前也写过类似的,不过那个时候只是一直半解,今天我就抽时间整合一下最近的理解。

结合一下ARM Cortex M3 系列的架构来进行分析。

一般我们在使用keil这个软件进行编译时可以看到在编译成功后

这里红色框框里的其实就是

Code为程序代码部分 = 程序代码区(code)

RO-data 表示 程序定义的常量 = 文字常量区

RW-data 表示 已初始化的全局变量 = 栈区(stack)堆区(heap)全局区(静态区)(static)

ZI-data 表示 未初始化的全局变量

单片机内存被总分为flash(rom)和sram(ram),flash里面的数据掉电可保存,sram中的数据掉电就丢失,sram的执行速度要快于flash,flash容量大于sram。一般下载的时候都是下载在FLASH里。

接下来我们再看一下下面这个图

这就是在代码中变量的存放位置。其实总共就分五个区,分别为栈区、堆区、全局区、代码区、常量区。

1.栈区:由编译器自动分配释放,存放函数的参数值、局部变量的值等。当调用函数的时候函数中定义的变量会被加到栈中,当函数离开的时候,被添加的变量会从栈中移除,栈在最高的地址上,所以添加的变量地址会逐渐变小,里面的内容可读可写。

2.堆区:一般由程序员分配和释放内存空间,例如我们在使用链表申请节点内存时,malloc函数申请的内存就是堆区的内存空间,使用完后要用free函数释放空间。里面的内容可读可写。

3.全局区/静态区:全局变量和静态变量就存放在这里,初始化且不为0的全局变量和静态局部变量在一块区域,这块区域我们称之为.data区。未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,这块区域我们称之为.bss区。程序结束后由系统释放,是由系统管理的可读可写的内存。

4.常量区:该内存区存放的常量,数字常量、字符常量、字符串常量等,不允许修改,所以常量区的内存是只读的。

5.代码区:存放程序的二进制代码,代码区的内容也是只读型。

这两个图的对应关系为

放个代码辅助理解

#include <stdio.h>

const int read_only_variable = 2000;

int data = 500;

void my_function(void)
{
    int x = 200;
    char *str = "string";
}

在上述代码中
read_only_variable 是一个用 const 修饰的全局变量,它是只读的,存放在 flash 中的只读数据区域,编译器会给 read_only_variable 分配一个地址,并将 2000 这个数据存放到常量区。

data 这个变量将存放到 RAM 中的RW区域中 (后面将会进行详细讲解),但是 data 后面的初始值 500 将会被存放到数据复制区域中, 也就是上图中从下往上的第三个区域。

在 my_function 中的变量 x 将会被存放到 RAM 中的堆栈中,将 x 赋值为 200 ,200 将被存储到 flash 里的 Text 中的常量区 (Literal Valu) 中。

str 是一个 char 型的指针变量,它指向的是字符串第一个字符存放的位置。

然而对于字符串 string 来讲,它是存放在Text常量区的,所以指针变量指向这个区域的一个地址,但是因为它终归中局部变量,它指向 Flash 的一个地址,但是其本身还是存放于 RAM 中的堆栈上的。

再举一个例子

#include <stdio.h>

#include <stdlib.h>

int data_var = 500;
int bss_var0;
int bss_var1 = 0;
static int static_var;

void my_function(void)

{

    static int static_var1 = 0;
    int stack = 0;
    char *buffer;
    const int value = 1;
    buffer = malloc(10);
}

上述变量的命名已经很清楚地表明了变量处于 RAM 中的哪一个段,datavar 是已经初始化的全局变量,存放在 RAM 的 data 区,bssvar0bssvar1是未初始化和初始化为0的全局变量,他们都存放于 RAM 中的 bss段,由 static 修饰的staticvarstatic_var1 都存放于 bss段,区别只在于两个变量的作用域不同。stack 是在函数内部定义的局部变量,其存放于 RAM 的区域,用 const 修饰的局部变量 value ,虽然他是只读的,但是它是存储于 RAM 中的中的,这里也说明一点,并不是所有用 const 修饰的变量都是存放于只读变量区的(const全局变量存储在只读数据段,编译期最初将其保存在符号表中,第一次使用时为其分配内存,在程序结束时释放,例如:val_c;const局部变量存储在栈中,代码块结束时释放,例如:val_j。)。buffer指针变量用 malloc 函数申请了 10 字节的内存空间,那这10字节的内存空间位于中。

函数指针参数

当调用 set 函数时,将一个常量整数的地址传递给函数参数 A,这个常量整数可以存储在不同位置。以下是一些示例:

  1. 常量整数存储在栈上

    #include <stdio.h>
    
    int set(const int *A) {
        printf("Value at address: %d\n", *A);
        return 0;
    }
    
    int main() {
        const int num = 10;  // 常量整数存储在栈上
        set(&num);  // 将常量整数的地址传递给 set 函数
        
        return 0;
    }
    

  2. 常量整数存储在全局数据段
     

    #include <stdio.h>
    
    const int globalNum = 20;  // 全局常量整数
    
    int set(const int *A) {
        printf("Value at address: %d\n", *A);
        return 0;
    }
    
    int main() {
        set(&globalNum);  // 将全局常量整数的地址传递给 set 函数
        
        return 0;
    }
    

3、常量整数存储在堆上

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

int set(const int *A) {
    printf("Value at address: %d\n", *A);
    return 0;
}

int main() {
    const int *ptr = (int*)malloc(sizeof(int));  // 分配内存存储常量整数
    *ptr = 30;  // 设置常量整数的值
    
    set(ptr);  // 将常量整数的地址传递给 set 函数
    
    free(ptr);  // 释放动态分配的内存
    
    return 0;
}

对于函数中被 const 修饰的参数,其存放位置取决于参数的类型和传递方式。一般来说,const 修饰的参数可能存放在以下几个位置:

  1. 栈上:如果参数是通过值传递(pass by value)或者以引用(指针)方式传递,并且函数内部并不修改该参数的值,那么这个参数通常会存放在栈上,即在函数调用时被压入栈中。

  2. 只读数据段:对于全局常量或静态常量作为参数并且被声明为 const 的情况,这些常量参数可能会存放在程序的只读数据段中,以确保在函数内部不会被修改。

  3. 堆上:如果参数是指向动态分配内存的指针,并且被声明为 const,那么这个指针可能指向堆上存储的数据,因为动态分配的内存是在堆上分配的。

  • 30
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内存资源分配 (Memory Resource Allocation) 是指在计算机系统,对内存进行合理的分配和管理,以满足不同程序的运行需求。 考虑到OD统一考试代码的特点和要求,内存资源分配需要满足以下几个方面的考虑: 1. 分配合适的内存大小:根据OD统一考试代码的实际需求,确定分配给每个程序的内存大小。过小的内存分配可能导致程序崩溃或运行缓慢,过大的内存分配则会浪费系统资源。 2. 确保内存安全性:在进行内存分配时,要避免出现内存泄漏和内存溢出的情况。内存泄漏指的是程序分配了内存但未释放,导致系统内存资源的浪费;而内存溢出指程序申请内存超过了实际可用的内存大小,导致程序异常终止。 3. 实时更新内存使用情况:对内存资源的分配和使用情况进行实时监控和更新,及时释放不再使用的内存,提高内存资源的利用率。 4. 优化算法和策略:为了提高内存资源的利用效率,可以采用一些优化算法和策略,例如使用内存池技术、实现内存碎片整理等,减少内存碎片和提高内存使用效率。 综上所述,内存资源分配对于OD统一考试代码非常重要。合理的内存分配能够提高程序的运行效率和稳定性,同时也可以优化系统的资源利用效率。因此,在进行内存资源分配时,需要充分考虑OD统一考试代码的特点和实际需求,并结合系统的内存管理策略,实现合理、高效的内存资源分配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值