[英]IAR Compiler: using struct with function pointers, map file shows all the function declared in struct irrespective of function used or not
我有一个带有 10 个函数指针的结构。 结构体的全局实例通过指向局部函数的函数指针进行初始化。 在我的应用程序中,使用任何一个或多个函数引用会导致链接器在映射文件中包含所有 10 个函数。
为了节省内存,我需要链接器只包含应用程序中使用的那些函数。 并非结构中引用的所有函数。
文件 r_adc_api.h 中的结构(来自制造商)
typedef struct st_adc_api
{
ssp_err_t (* open)(adc_ctrl_t * const p_ctrl, adc_cfg_t const * const p_cfg);
ssp_err_t (* scanCfg)(adc_ctrl_t * const p_ctrl, adc_channel_cfg_t const * const p_channel_cfg);
ssp_err_t (* scanStart)(adc_ctrl_t * const p_ctrl);
ssp_err_t (* scanStop)(adc_ctrl_t * const p_ctrl);
ssp_err_t (* scanStatusGet)(adc_ctrl_t * const p_ctrl);
ssp_err_t (* read)(adc_ctrl_t * const p_ctrl, adc_register_t const reg_id, adc_data_size_t * const p_data);
ssp_err_t (* sampleStateCountSet)(adc_ctrl_t * const p_ctrl, adc_sample_state_t * p_sample);
ssp_err_t (* close)(adc_ctrl_t * const p_ctrl);
ssp_err_t (* infoGet) (adc_ctrl_t * const p_ctrl, adc_info_t * const p_adc_info);
ssp_err_t (* versionGet)(ssp_version_t * const p_version);
} adc_api_t;
**头文件 r_adc.h **(来自制造商)
extern const adc_api_t g_adc_on_adc;
赋值和函数定义在文件 r_adc.c (来自制造商)中
const adc_api_t g_adc_on_adc =
{
.open = R_ADC_Open,
.scanCfg = R_ADC_ScanConfigure,
.infoGet = R_ADC_InfoGet,
.scanStart = R_ADC_ScanStart,
.scanStop = R_ADC_ScanStop,
.scanStatusGet = R_ADC_CheckScanDone,
.sampleStateCountSet = R_ADC_SetSampleStateCount,
.read = R_ADC_Read,
.close = R_ADC_Close,
.versionGet = R_ADC_VersionGet
};
和## 函数定义##
** 地图文件 **地图文件
在我的应用程序中,如果我使用 adc_on_g_adc.open(...); 链接器将所有 10 个符号拉到映射文件中,而不仅仅是拉R_ADC_Open();
即使调用了一个函数,也可能导致 .map 文件从结构中提取所有函数?
编辑:将所有这些放在一个文件中给出了我需要的地图文件。 IAR 编译器省略了未使用的函数。 当我使用多个标题和源时,它不起作用。
如果用函数指针填充结构,就链接器而言,这些函数已被“使用”。
根据链接器应该用什么来替换R_ADC_ScanConfigure
来R_ADC_ScanConfigure
它。 它不能选择将g_adc_on_adc.scanCfg
设置为 NULL,可以吗? 它不知道目标代码实际上并未调用g_adc_on_adc.scanCfg
。
基本上,唯一的选择是在输出中包含R_ADC_ScanConfigure
。
然而,如果不是分配R_ADC_ScanConfigure
在结构设置g_adc_on_adc.scanCfg
为NULL,连接器然后能省略R_ADC_ScanConfigure
从输出。
const adc_api_t g_adc_on_adc =
{
.open = R_ADC_Open,
.scanCfg = NULL,
.infoGet = R_ADC_InfoGet,
.scanStart = R_ADC_ScanStart,
.scanStop = R_ADC_ScanStop,
.scanStatusGet = R_ADC_CheckScanDone,
.sampleStateCountSet = R_ADC_SetSampleStateCount,
.read = R_ADC_Read,
.close = R_ADC_Close,
.versionGet = R_ADC_VersionGet
};
当然,如果您的代码最终确实调用了g_adc_on_adc.scanCfg
那么您将尝试在地址 0(可能)运行代码,这确实是一件非常糟糕的事情。 您可以让.scanCfg
指向一个函数,该函数只是在您的控制台/串行端口/任何东西上打印出令人讨厌的错误消息,以便至少您知道出现了问题。
您正在寻找的功能称为虚函数消除,它可以满足您的需求,但仅适用于 C++ 中的虚函数。
在你的代码中,编译器看到的只是一个用一些指向函数的指针初始化的结构。 如果此结构是全局的或以某种方式从该模块导出,则编译器必须假定使用了该结构的所有初始化部分。
当链接器掌握所有这些时,它会看到对结构的引用,仅此而已。 那里没有信息告诉链接器使用了结构的哪一部分。
当你把所有东西都放在同一个模块中时,编译器可以找出你实际引用的函数并直接去那里,这将使结构没有引用,这意味着它可以被丢弃,并且所有对其他函数的引用都会被丢弃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.