Const 在受限设备上的功能
Const in function on constrained devices
我只是有一个关于 C 语言在受限设备上的内存管理的简短问题。
一般来说:全局常量变量最终会出现在微控制器的闪存中。
本地定义的变量最终在堆栈上,因此在内存中。
但是在函数中定义的 const 变量呢?它们只是在堆栈中结束,对吧,因为它们仅在函数内局部可用,并且需要在执行函数后清除。还是他们最终会出现在闪光灯中?
“全局常量变量最终出现在微控制器的闪存中”
不,.
“函数中定义的常量变量”
他们最终 on the stack.
flash 的一部分用于指令代码(通过您的 IDE/flashing 工具),否则需要明确使用。
(因为闪存的写入周期有限)
C 中的主要内存模型如下所示:
五段定义为:
- 代码段 - 存储
code
部分,ROM
- 数据段 - 存储已初始化
global
和static
变量
- 堆栈段 - 存储局部变量、函数参数、return地址。这进一步细分为
frames of stacks
.
- 堆段 - 动态分配在这里发生,如
malloc
。
- BSS(或由符号开始的块)段 - 存储未初始化的
global
和 static
变量
const
关键字对编译器来说是 qualifier,它必须存储在内存段的写保护区域中,现在编译器必须决定它必须去哪里:
如果是 unitialised -> bss
否则 initialised -> data segment
在微控制器中(memory model) ROM memory is on FLASH, for microcontroller memory details here。
免责声明: 许多但不一定是所有嵌入式编译器系统都以类似的方式工作。我试图在一些简化的陈述中浓缩我 30 多年的嵌入式系统工作经验。对于 任何 嵌入式系统,不要认为它们是理所当然的。
global const variables end up in the flash of the microcontroller.
全局变量是静态变量。静态常量变量通常放在只读初始化数据的部分中。这不一定是与可执行代码相同的部分,但它可能是。
但是,链接器将此类(逻辑)部分组合成(物理)部分。如果目标为此使用闪存,则全局常量变量将在闪存中。
一些链接器以不同方式处理这些数据部分,并将它们放在 RAM 中。 const
限定符可用于对 RAM 区域进行写保护的内存管理单元。不管怎样,编译器会检查你是否没有写入这些变量,只要它能做到这一点。
Variables locally defined end up on the stack, therefore in the memory.
这在很大程度上取决于系统和变量的限定符。
- 优化可能会将局部变量放在寄存器中。
- 优化可能根本不为常量分配位置并直接使用该值。
- 您可以对局部变量使用
static
。然后这个变量只在定义它的块内部及其内部块中可见。但它的位置通常与全局变量相同。它将在整个 运行 时间内保持其价值。
- 您可以对局部变量使用
const
和 static
。这通常会将此变量放在与全局常量变量相同的部分。
- 真正受限的系统,如 8051,仅在需要时才对局部变量使用堆栈,例如,如果需要递归。最常见的编译器和链接器分析生命周期并将局部变量静态放置在公共部分中。相同的内存位置将用于具有非重叠生命周期的不同局部变量。
But how about const variables defined in functions? They just end up in the stack, [...] Or do they end up in the flash?
结论1:添加正确的限定符,很可能会放在你想要的地方。
结论 2:您需要阅读 您的 系统的文档。您需要做一些实验,检查链接器的映射文件。
注意 1:许多系统都有一种或另一种方法来进一步控制放置。例如,对于 GCC,您可以使用 __attribute__((section("any-section-you-like")))
将对象分配给另一个部分。链接描述文件也是某种方式。
注 2:我使用的大多数嵌入式系统都不会“加载”程序。可执行代码将 运行 就地。同样,静态常量变量不会被加载,而是从内存中读取它们存储在非易失性内存中。
我只是有一个关于 C 语言在受限设备上的内存管理的简短问题。 一般来说:全局常量变量最终会出现在微控制器的闪存中。 本地定义的变量最终在堆栈上,因此在内存中。 但是在函数中定义的 const 变量呢?它们只是在堆栈中结束,对吧,因为它们仅在函数内局部可用,并且需要在执行函数后清除。还是他们最终会出现在闪光灯中?
“全局常量变量最终出现在微控制器的闪存中”
不,
“函数中定义的常量变量” 他们最终 on the stack.
flash 的一部分用于指令代码(通过您的 IDE/flashing 工具),否则需要明确使用。 (因为闪存的写入周期有限)
C 中的主要内存模型如下所示:
五段定义为:
- 代码段 - 存储
code
部分,ROM - 数据段 - 存储已初始化
global
和static
变量 - 堆栈段 - 存储局部变量、函数参数、return地址。这进一步细分为
frames of stacks
. - 堆段 - 动态分配在这里发生,如
malloc
。 - BSS(或由符号开始的块)段 - 存储未初始化的
global
和static
变量
const
关键字对编译器来说是 qualifier,它必须存储在内存段的写保护区域中,现在编译器必须决定它必须去哪里:
如果是 unitialised -> bss
否则 initialised -> data segment
在微控制器中(memory model) ROM memory is on FLASH, for microcontroller memory details here。
免责声明: 许多但不一定是所有嵌入式编译器系统都以类似的方式工作。我试图在一些简化的陈述中浓缩我 30 多年的嵌入式系统工作经验。对于 任何 嵌入式系统,不要认为它们是理所当然的。
global const variables end up in the flash of the microcontroller.
全局变量是静态变量。静态常量变量通常放在只读初始化数据的部分中。这不一定是与可执行代码相同的部分,但它可能是。
但是,链接器将此类(逻辑)部分组合成(物理)部分。如果目标为此使用闪存,则全局常量变量将在闪存中。
一些链接器以不同方式处理这些数据部分,并将它们放在 RAM 中。 const
限定符可用于对 RAM 区域进行写保护的内存管理单元。不管怎样,编译器会检查你是否没有写入这些变量,只要它能做到这一点。
Variables locally defined end up on the stack, therefore in the memory.
这在很大程度上取决于系统和变量的限定符。
- 优化可能会将局部变量放在寄存器中。
- 优化可能根本不为常量分配位置并直接使用该值。
- 您可以对局部变量使用
static
。然后这个变量只在定义它的块内部及其内部块中可见。但它的位置通常与全局变量相同。它将在整个 运行 时间内保持其价值。 - 您可以对局部变量使用
const
和static
。这通常会将此变量放在与全局常量变量相同的部分。 - 真正受限的系统,如 8051,仅在需要时才对局部变量使用堆栈,例如,如果需要递归。最常见的编译器和链接器分析生命周期并将局部变量静态放置在公共部分中。相同的内存位置将用于具有非重叠生命周期的不同局部变量。
But how about const variables defined in functions? They just end up in the stack, [...] Or do they end up in the flash?
结论1:添加正确的限定符,很可能会放在你想要的地方。
结论 2:您需要阅读 您的 系统的文档。您需要做一些实验,检查链接器的映射文件。
注意 1:许多系统都有一种或另一种方法来进一步控制放置。例如,对于 GCC,您可以使用 __attribute__((section("any-section-you-like")))
将对象分配给另一个部分。链接描述文件也是某种方式。
注 2:我使用的大多数嵌入式系统都不会“加载”程序。可执行代码将 运行 就地。同样,静态常量变量不会被加载,而是从内存中读取它们存储在非易失性内存中。