简体   繁体   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

I have a struct with 10 function pointers.我有一个带有 10 个函数指针的结构。 A global instance of the struct is initialized wit function pointers pointing to local functions.结构体的全局实例通过指向局部函数的函数指针进行初始化。 In my application, using any one or more of the function references causes linker to include all 10 functions in the map file.在我的应用程序中,使用任何一个或多个函数引用会导致链接器在映射文件中包含所有 10 个函数。

In order to save memory, I need linker to include onle those functions that used in the application.为了节省内存,我需要链接器只包含应用程序中使用的那些函数。 Not all the functions referenced in the struct.并非结构中引用的所有函数。

Struct in file r_adc_api.h (from Manufacturer)文件 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;

**Header r_adc.h ** (from Manufacturer) **头文件 r_adc.h **(来自制造商)

extern const adc_api_t g_adc_on_adc;

Assignment and function definitions is in file r_adc.c (from Manufacturer)赋值和函数定义在文件 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
};

and ## Function Definitions ##和## 函数定义##

** MAP File ** MAP file ** 地图文件 **地图文件

In my Application, if i use adc_on_g_adc.open(...);在我的应用程序中,如果我使用 adc_on_g_adc.open(...); linker pulls all 10 symbols to the map file instead of just pulling R_ADC_Open();链接器将所有 10 个符号拉到映射文件中,而不仅仅是拉R_ADC_Open();

What might be causing .map file to pull all the functions from the struct even if one function is called?即使调用了一个函数,也可能导致 .map 文件从结构中提取所有函数?

Edit: Putting all these together in one single file gives map file I need.编辑:将所有这些放在一个文件中给出了我需要的地图文件。 IAR compiler omits unused functions. IAR 编译器省略了未使用的函数。 Just doesn't work when I use multiple header and source.当我使用多个标题和源时,它不起作用。

If you fill up the structure with function pointers, the functions have been "used" so far as the linker is concerned.如果用函数指针填充结构,就链接器而言,这些函数已被“使用”。

Think about it in terms of what the linker is supposed to replace R_ADC_ScanConfigure with.根据链接器应该用什么来替换R_ADC_ScanConfigureR_ADC_ScanConfigure它。 It can't choose to set g_adc_on_adc.scanCfg to NULL, can it?它不能选择将g_adc_on_adc.scanCfg设置为 NULL,可以吗? It doesn't know that the object code doesn't actually call g_adc_on_adc.scanCfg .它不知道目标代码实际上并未调用g_adc_on_adc.scanCfg

Basically, it's only option is to include R_ADC_ScanConfigure in the output.基本上,唯一的选择是在输出中包含R_ADC_ScanConfigure

However, if instead of assigning R_ADC_ScanConfigure in the structure you set g_adc_on_adc.scanCfg to NULL, the linker would then be able omit R_ADC_ScanConfigure from the output.然而,如果不是分配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
};

Of course, if your code then did end up calling g_adc_on_adc.scanCfg you'd be trying to run code at address 0 (probably), which would be a very bad thing indeed.当然,如果您的代码最终确实调用了g_adc_on_adc.scanCfg那么您将尝试在地址 0(可能)运行代码,这确实是一件非常糟糕的事情。 You could make .scanCfg point to a function that simply prints up a nasty error message on your console / down your serial port / whatever so that at least you know something has gone wrong.您可以让.scanCfg指向一个函数,该函数只是在您的控制台/串行端口/任何东西上打印出令人讨厌的错误消息,以便至少您知道出现了问题。

The feature you are looking for is called virtual function elimination and does just what you want but for only for virtual functions in C++.您正在寻找的功能称为虚函数消除,它可以满足您的需求,但仅适用于 C++ 中的虚函数。

In your code all the compiler sees is a structure initialized with some pointers to functions.在你的代码中,编译器看到的只是一个用一些指向函数的指针初始化的结构。 If this structure is global or somehow exported from this module the compiler must assume that all the initialized parts of the structure are used.如果此结构是全局的或以某种方式从该模块导出,则编译器必须假定使用了该结构的所有初始化部分。

When the linker gets hold of all this it sees a reference to the structure, that's all.当链接器掌握所有这些时,它会看到对结构的引用,仅此而已。 There is no information there to tell the linker what part of the structure is used.那里没有信息告诉链接器使用了结构的哪一部分。

When you put everything in the same module the compiler can find out what function you actually reference and go there directly, this will leave the structure without references meaning it can be thrown away and with it all the references to the other functions.当你把所有东西都放在同一个模块中时,编译器可以找出你实际引用的函数并直接去那里,这将使结构没有引用,这意味着它可以被丢弃,并且所有对其他函数的引用都会被丢弃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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