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