繁体   English   中英

IAR 编译器:使用带有函数指针的 struct,映射文件显示所有在 struct 中声明的函数,而不管是否使用了函数

[英]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_ScanConfigureR_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM