STM32链接器脚本初始化部分,使用C时需要它们吗?

Posted

技术标签:

【中文标题】STM32链接器脚本初始化部分,使用C时需要它们吗?【英文标题】:STM32 linkerscript initialization sections, are they needed when using C? 【发布时间】:2021-08-13 23:00:27 【问题描述】:

据我所知,STM32CubeIDE 链接器脚本中的 .init、.preinit_array、.init_array、.finit、.fini_array... 等部分在 C++ 中用于调用需要在 main 之前执行的静态对象的构造函数(以及析构函数的 fini 版本)。

我的假设是这些部分被编译器和 C/C++ 运行时库隐式调用的函数使用,但是如果您的固件是用 C 编写的,那么真的需要所有这些部分吗?编译器在幕后做了什么?

【问题讨论】:

不,对于裸机 C 代码,通常不需要这些。 【参考方案1】:

你可以在没有他们的情况下生活。

除了 C++,其中一些可能会初始化标准库所需的东西。如果您只从标准库中调用pure 函数,并且您只有 C 或汇编中的代码,那么您可以尝试将它们取出。

如果您想将其作为一种学习练习,请将它们拿出来,看看什么不起作用。另外在谷歌上搜索,有loadsofsites以一种太长的方式来解释这种事情,在这里无法重现。

如果您只是想完成您的项目,那就别管他们了。它们只会使您的程序大小增加一点点,不值得您花时间与它们抗争。

【讨论】:

C 编译器真的会发出它们吗?因为如果没有,那么链接描述文件中未使用的部分可能不会使用 ROM 和 RAM 上的空间。 启动文件的这些部分中有一些字节。您可以使用 -nostartfiles 来省略它们,但除了作为学习练习之外,我不建议这样做。 @jap-jap 如果这解决了你的问题,你能接受左边有勾号的答案吗?【参考方案2】:

在 C++ 中用于调用需要的静态对象的构造函数 在 main 之前执行(以及 析构函数)。

这不是 100% 的真理。 cubeIDE 使用基于 gcc 的 ARM 工具链,该工具链具有一些可能使用其中一些部分的扩展。例如,您可以使用 use 属性来创建将在 main 之前执行和/或在 main 函数返回之后调用的函数。

void __attribute__((constructor)) called_before_main(void)

   /* some code */


void __attribute__((destructor)) called_after_main(void)

   /* some code */

如果您甚至不使用其中任何一个,外部库也可能会使用它们。即使您不使用外部库,保留这些部分也不会受到影响,因为如果它们为空,它们将被丢弃。

【讨论】:

以上是关于STM32链接器脚本初始化部分,使用C时需要它们吗?的主要内容,如果未能解决你的问题,请参考以下文章

STM32 链接器脚本仅用于来自 FLASH 的启动脚本,其他一切来自 RAM

STM32 Eclipse + ARM GNU 工具链错误链接器

AVR - GNU 链接器脚本 - 如何获取 .data 部分的加载地址

为啥链接器无法识别我的链接器脚本中定义的入口点

为啥 STM32 gcc 链接器脚本会自动丢弃这些标准库中的所有输入节:libc.a、libm.a、libgcc.a?

stm32全局数组上电时会加载到内存吗