- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有带闪存的 MCU(像往常一样)。链接器将 .struct_init、.struct_init_const、.struct_not_init 部分放置到属于闪存部分 20 的地址。它在链接器脚本中被硬编码。
考虑以下测试代码:测试.h
typedef struct
{
int val1;
int val2;
} mystruct_t;
测试.cpp
#include "test.h"
// each variable is placed in dedicated section
// sections are placed in flash section20
// linker exports symbols with address of eaach section
__attribute__((section(".struct_init")))
mystruct_t struct_init = {
.val1 = 1,.val2 = 2};
__attribute__((section(".struct_init_const")))
extern const mystruct_t struct_init_const = {
.val1 = 1, .val2 = 2};
__attribute__((section(".struct_not_init")))
mystruct_t struct_not_init;
主要.cpp
#include <stdint.h>
// This symbols exported by linker
// contains addresses of corresponding sections
extern uintptr_t LNK_STRUCT_INIT_ADDR;
extern uintptr_t LNK_STRUCT_INIT_CONST_ADDR;
extern uintptr_t LNK_STRUCT_NOT_INIT_ADDR;
// Pointers for indirect access to data
mystruct_t* struct_init_ptr = (mystruct_t*)LNK_STRUCT_INIT_ADDR;
const mystruct_t* struct_init_const_ptr = (const mystruct_t*)LNK_STRUCT_INIT_CONST_ADDR;
mystruct_t* struct_not_init_ptr = (mystruct_t*)LNK_STRUCT_NOT_INIT_ADDR;
// Extern variables declarations for DIRECT access data
extern mystruct_t struct_init;
extern const mystruct_t struct_init_const;
extern mystruct_t struct_not_init;
// This is some variables representing config values
// They can be more complex objects(classes) with internal state and logic..
int param1_direct;
int param1_init_const_direct;
int param1_not_init_direct;
int param1_indirect;
int param2_init_const_indirect;
int param1_not_init_indirect;
int main(void)
{
// local variables init with direct access
int param1_direct_local = struct_init.val1;
int param1_init_const_direct_local = struct_init_const.val1;
int param1_not_init_direct_local = struct_not_init.val1;
// local variables init with indirect access
int param1_indirect_local = struct_init_ptr->val1;
int param2_init_const_indirect_local = struct_init_const_ptr->val1;
int param1_not_init_indirect_local = struct_not_init_ptr->val1;
//global variables init direct
param1_direct = struct_init.val1;
param1_init_const_direct = struct_init_const.val1;
param1_not_init_direct = struct_not_init.val1;
//global variables init indirect
param1_indirect = struct_init_ptr->val1;
param2_init_const_indirect = struct_init_const_ptr->val1;
param1_not_init_indirect = struct_not_init_ptr->val1;
while(1){
// use all variables we init above
// usage of variables may also occure in some functions or methods
// directly or indirectly called from this loop
}
}
我想确保 param1_ 变量的初始化会导致从闪存中获取数据。因为flash section20中的数据可以使用bootloader来改变(在主固件没有运行的那一刻)。
问题是:LTO(和其他优化)是否可以丢弃从闪存中获取的数据并仅替换已知值,因为由于初始化,它们在链接时是已知的。什么方法更好?如果 LTO 可以替换值——那么应该避免初始化吗?我知道 volatile 可以提供帮助,但在这种情况下真的需要它吗?
代码示例展示了访问和初始化数据的不同方法。not_init 版本似乎是最好的,因为编译器不能替代任何东西。但是有一些默认参数是个好主意,所以如果可以使用,我更喜欢 init 版本。
应该选择什么方法?
目前我使用的是 GCC 4.9.3,但这是关于任何 C/C++ 编译器的普遍问题。
最佳答案
C 和 C++ 都具有 extern
变量,它允许您定义常量而不立即放弃它们的值:
// .h
extern int const param1;
extern char const* const param2;
// ...
通常,您会在(单个)源文件中定义它们,这会将它们隐藏起来,远离此源文件中不的任何内容。当然,这不是 LTO 弹性,但如果您可以禁用 LTO,这是一个非常简单的策略。
如果禁用 LTO 不是一个选项,另一种解决方案是不定义它们,让 LTO 生成一个二进制文件,然后使用脚本将生成的二进制文件中的定义拼接在正确的部分(可以闪存的部分) .
在 LTO 时间不可用的值,您保证不会被替换。
至于您提供的解决方案,虽然 volatile
确实是一个符合标准的解决方案,但它意味着该值不是常量,这会阻止在运行时对其进行缓存。这是否可以接受由您自己决定,请注意它可能会对性能产生影响,而当您使用 LTO 时,我推测您希望避免这种情况。
关于c++ - LTO 优化负面影响并找到最佳解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31348093/
我正在使用 CMake 为我的 C 编译启用 IPO(过程间优化): set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRU
我正在使用 CMake 为我的 C 编译启用 IPO(过程间优化): set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRU
我一直在尝试使用以下代码片段(gcc 编译时没有任何警告)更改 Windows(7 和 Server 2012 R2)中 LTO8 磁带的事件分区: DWORD partition= 2; if(Se
考虑以下程序: #include #include int main() { std::string s; std::getline(std::cin, s);
我正在使用链接时间优化 (lto) 和 O2 优化级别编译一个带有修改版 clang 的项目。 O0 和 O1 都很好,但遗憾的是 O2 删除了一些函数调用。有没有办法告诉优化忽略特定功能?我已经尝试
我有带闪存的 MCU(像往常一样)。链接器将 .struct_init、.struct_init_const、.struct_not_init 部分放置到属于闪存部分 20 的地址。它在链接器脚本中被
在编译翻译单元时,编译器会进行大量优化 - 内联、常量折叠/传播、别名分析、循环展开、死代码消除以及许多我从未听说过的其他优化。在多个翻译单元之间使用 LTO/LTCG/WPO 时是否全部完成,或者只
比较 C++ 中的虚函数和 C 中的虚表,编译器在一般情况下(以及对于足够大的项目)在去虚拟化方面是否同样出色? 天真地,C++ 中的虚函数似乎具有更多的语义,因此可能更容易去虚拟化。 更新: Moo
GCC、MSVC、LLVM 和可能的其他工具链支持链接时间(整个程序)优化,以允许优化编译单元之间的调用。 编译生产软件时是否有理由不启用此选项? 最佳答案 我假设 “生产软件” 是指您交付给客户/投
有没有办法检测代码是否是用 -flto 编译的? 示例是Linux下的经典库或可执行文件,使用GCC(4.9.1)编译,无需调试。 最佳答案 考虑到 LTO 信息存储在目标文件内的几个 ELF 部分中
假设我有一个函数 void do_something() { //.... #ifdef FEATURE_X feature_x(); #endif /
对于 gcc,这个 answer告诉我们如何验证链接时间优化是否已执行。对于 clang,我看不到任何类似于 .gnu.lto 的条目. 更具体地说,我有一个二进制文件,我很确定 LTO 应该有很大的
我试图用下一个标志编译我的源代码: 1. -flto2. -flto -ffat-lto-objects3. -flto -fno-fat-lto-objects 第三个提供优化slim文档中编写的
我有一个项目,在 ARM Cortex-M4 处理器上运行,我试图在其中包含 gcc 链接时优化 (LTO) 功能。 目前我的编译和链接标志是: CFLAGS = -ggdb -ffunction-s
在编写代码或构建脚本以使用 LTO 进行编译时需要牢记哪些注意事项和陷阱? 这个问题背后的动机是为了更好地理解为什么某些项目在启用 LTO 时编译不干净。特别是,我无法构建 ICU在启用 LTO 的情
我想使用符号版本控制和链接时优化 (LTO) 编译共享库。但是,一旦我打开 LTO,一些导出的符号就会消失。这是一个最小的例子: 首先定义函数 fun 的两个实现: $ cat fun.c #incl
当我尝试使用 -flto 构建静态库时,出现 undefined reference 错误: library.cpp: #include void foo() { std::cout << "T
Clang 允许使用瘦 lto 来加快编译时间,同时仍然保留使用 lto 和选项 -flto=thin 的大部分优点。 . gcc 有相当于 clang 的薄 lto 吗? 最佳答案 GCC 有一个相
我正在使用 arm-none-eabi-gcc 为基于 Cortex-M4 的微 Controller 编译一个可执行文件。非性能关键代码使用 -Os(针对可执行代码大小进行了优化)编译,性能关键部分
有这样的代码: #include "kernel.h" int main() { ... for (int t = 0; t 1099: 00 109a: f
我是一名优秀的程序员,十分优秀!