함수포인터를 사용하여 바이너리 파일 크기를 줄여보자.

Posted by ceyx
2017. 5. 23. 11:39 카테고리 없음
프로그램의 기능이 많아지면 #define 등의 지시문을 통해 해당 기능의 활성화를 설정합니다.

보통은 소스코드에  a, b, c 라는 기능을 다 구현해 놓고 릴리즈 할때 조건에 따라 a 기능을 활성화 할지, b 기능을 활성화 할지 또는 전부 활성화/비활성화 할지 여부를 결정하게 되는데요.

사용하지 않는 기능은 빼고 바이너리 파일을 만든다면 크기가 줄어 들겠지요.
이번 글은 함수 포인터를 이용해서 바이너리 파일의 크기를 줄일수 있는 방법에 대해 설명하겠습니다.

일반적으로 소스코드를 빌드하면 object 파일이 만들어지고 
링커스크립트를 통해 바이너리 파일과 ELF 파일이 생성됩니다. 

아래 그림은 ARM 기반으로 이와 같은 과정을 보여줍니다.

 


오브젝트 파일은 소스코드가 다 빌드되어 포함되지만 실제 사용하는 기능들은 링커스크립트가 동작하면서
선별하여 bin 파일이 만들어집니다.
보통은 직접 호출하는 함수들은 어김없이 들어갑니다만...
함수 포인터를 사용하여 해당 함수를 간접 호출 함으로써 필요없는 기능은 bin파일에 포함되지 않도록 할수 있습니다. 

다음과 같이 필요한 기능을 구현한 함수가 있습니다.

 

함수가 호출되면 코드상의 printf()를 통해 "Call testFunction1" 이라는 문구가 출력 되겠지요.


일반적으로 이 함수를 testFunction1(); 이렇게 호출하면 해당 함수가 수행 합니다.
여기서는 직접 호출하지 않고 함수 포인터에 등록 해봅시다.

 

먼저 함수 포인터를 선언합니다.

 

 

Function 은 다음과 같이 선언됩니다.

 


리턴값이 있는 함수는 Function 이라는 이름으로, 리턴값이 없는것은 VoidFunction이라고 지정합니다.
그럼 이제 함수포인터 nDTestFunction 에 해당 함수를 할당하는 함수를 만들어 봅니다.

 

 

이 함수의 호출 여부로 함수포인터에 함수를 할당 할지 여부를 결정할수 있습니다. 
이 함수가 수행되지 않으면 당연히 함수포인터는 NULL로 유지 되겠지요.

이제 해당 기능의 활성화 여부를 결정하는 #define CONFIG_TEST_FUNC 가 활성화 되었을때만 
DASetActivate() 함수를 호출 하면 되겠네요.

 

 

#define CONFIG_TEST_FUNC가 선언되지 않으면 nDTestFunction은 NULL 상태일 겁니다.

맨 처음 만들었던 필요한 기능을 수행 하는 함수 testFunction1 의 호출은 
다음과 같이 함수 포인터를 호출하는걸로 대신 할수 있습니다.

 

 

위와 같이 nDTestFunction이 NULL 이 아닐때,

즉 DASetActivate() 함수가 호출되어 함수 포인터에 testFunction1() 함수가 할당 되었을때만 수행하도록 합니다.

위와 같이 구현하고 빌드한 후 map 파일을 열어보면 testFunction1의 존재 여부가 달라집니다.

#define CONFIG_TEST_FUNC 활성화

 

 

 
중간에 testFunction1이 있습니다.

#define CONFIG_TEST_FUNC 비활성화

 

 
testFunction1 함수가 있던 곳은 다른 함수들로 채워져 있습니다.

활성화 후 실행 하면 다음과 같이 정상적으로 수행됩니다.

이와 같이 함수 포인터를 사용하여

필요없는 기능은 포함시키지 않고 바이너리 파일을 생성함으로써 크기가 그만큼 작게 만들어집니다.

감사합니다.