2017-03-08 1 views
1

구조체에 10 개의 함수 포인터가 있습니다. 구조체의 전역 인스턴스는 로컬 함수를 가리키는 초기화 된 함수 포인터입니다. 내 응용 프로그램에서 하나 이상의 함수 참조를 사용하면 링커가 맵 파일에 10 개의 모든 함수를 포함시킵니다.IAR 컴파일러 : 구조체를 함수 포인터와 함께 사용하면 맵 파일에 함수에 관계없이 구조체에 선언 된 모든 함수가 표시됩니다.

메모리를 절약하기 위해 애플리케이션에 사용 된 기능을 링커에 포함시켜야합니다. 구조체에서 참조되는 모든 함수가 아닙니다. (제조업체) 파일 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 
}; 

및 ## 함수 정의 ##

** MAP 파일 ** 내 응용 프로그램에서 MAP file

, 내가 adc_on_g_adc.open (...)를 사용하는 경우; 링커가 당기는 대신 모든 10 개의 심볼을 맵 파일로 가져옵니다. R_ADC_Open();

하나의 함수가 호출 되더라도 .map 파일이 구조체의 모든 함수를 가져 오는 원인은 무엇입니까?

편집 :이 모든 것을 하나의 파일로 묶어서 필요한 맵 파일을 제공합니다. IAR 컴파일러는 사용하지 않는 함수를 생략합니다. 헤더와 소스를 여러 개 사용할 때만 작동하지 않습니다.

+0

우선, ***. h ** 파일의 각 정적 할당은 다른 경우에 사용한 횟수만큼 복사됩니다. 둘째, 달성하고자하는 것이 명확하지 않습니까? 콜백 구조의 동적 크기? 런타임에 함수를 등록하는 함수 목록이있는 경우에는 준 변환 할 수 있습니다. 이것이 플러그인이 일반적으로 등록되는 방법입니다. – 0andriy

+0

0andriy, 답장을 보내 주셔서 감사합니다. 이것은 제조업체에서 제공 한 것으로 일부 변경 사항과 함께 사용해야합니다. 이 일을하기위한 그들의 생각은 함수 호출에서 일어나는 일들에 대해 많은 걱정없이 인터페이스 (함수 포인터)를 사용하는 것입니다. 나는 코드 섹션 최적화 때문에 그것의 내부에서 놀고있다. –

+0

질문이 명확하지 않습니다. 단어의 양을 줄이고 간단한 예를 들면 다음과 같습니다. a) 존재하는 것과 b) 달성하고자하는 것. – 0andriy

답변

1

함수 포인터로 구조체를 채우는 경우 함수는 링커와 관련하여 "사용 된"것입니다.

링커가 R_ADC_ScanConfigure을 (를) 대체 할 대상으로 생각하십시오. g_adc_on_adc.scanCfg을 NULL로 설정할 수는 없습니까? 오브젝트 코드가 실제로 g_adc_on_adc.scanCfg을 호출하지 않는지는 알 수 없습니다.

기본적으로 출력에 R_ADC_ScanConfigure을 포함하는 것이 유일한 옵션입니다.

그러나, 대신이 NULL로 g_adc_on_adc.scanCfg을 설정 구조에 R_ADC_ScanConfigure를 할당하는 링커는 다음 출력에서 ​​수 생략 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 
}; 

, 코드가 당신이 참으로 아주 나쁜 일이 될 것입니다 (아마도) 주소 0에서 코드를 실행하려고 할 것 g_adc_on_adc.scanCfg 호출 끝 않은 경우. .scanCfg은 단순히 콘솔에 불쾌한 오류 메시지를 인쇄하는 기능을 가리킬 수 있습니다. 직렬 포트/무엇이든간에 적어도 뭔가 잘못되었다는 것을 알기 위해서입니다.

+0

답변 해 주셔서 감사합니다. Pls 내 질문에 질문을 확인하십시오. 이 모든 코드를 하나의 파일에 함께 사용하면 필요한 링커 출력을 얻을 수 있습니다. 즉, 하나의 함수를 사용하면 MAP 파일에는 해당 함수 만 있습니다. 여러 헤더 및 소스 파일에 흩어져있는 코드에서는 작동하지 않습니다. 필자가 생각하기에, 올바른 범위를 사용하거나 링크 할 수있는 옵션이나 내가 모르는 어떤 것. 어쨌든, 나는 분명히 당신이 제안하고있는 것처럼 함수 참조로 놀고 싶지 않습니다. 링커가 하나의 파일에 코드의 경우처럼 분산 된 코드에서 사용하지 않는 함수를 알 수있는 방법이 있어야합니다. –

+1

모든 것을 하나의 파일에 모아서 컴파일러가'g_adc_on_adc' 구조체의 일부가 완전히 사용되지 않고 있다는 것을 인식하고 그들을 최적화 할 수 있습니다. 사용되지 않는 변수를 선언하는 것과 같은 비트 - 컴파일러는 단순히 그것들을 모두 제거합니다. – bazza

+0

그러나 원하는 옵션을 수행 할 수있는 링크 옵션이 없습니다.함수에 할당 된 모든 필드와 함께'g_adc_on_adc'를 선언하고 컴파일러가 여러 소스 코드 파일을 가지고 있기 때문에 사용하지 않는 필드를 최적화 할 기회가 없다면 링커는 결과 함수에 참조 된 함수를 포함 할 수밖에 없습니다 실행 파일. – bazza

0

찾고있는 기능을 가상 함수 제거라고하며, C++의 가상 함수에만 사용할 수 있습니다.

코드에서 모든 컴파일러는 함수에 대한 몇 가지 포인터로 초기화 된 구조입니다. 이 구조가 전역이거나이 모듈에서 어떻게 든 내 보낸다면 컴파일러는 구조체의 모든 초기화 된 부분이 사용된다고 가정해야합니다.

링커가이 모든 것을 유지하면 구조에 대한 참조가 표시됩니다. 링커에게 구조의 어떤 부분이 사용되는지 알려주는 정보는 없습니다.

동일한 모듈에 모든 것을 넣으면 컴파일러는 실제로 어떤 함수를 참조하고 직접 찾아갈 수 있는지 알려주지 만 참조없이 구조체를 벗어나 버리면 다른 함수에 대한 모든 참조가 삭제됩니다 .

관련 문제