簡體   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