본문 바로가기

별걸다하는 IT/프로그래밍언어

[로그 출력 함수 만들기]현재 파일명, 함수명, 라인 번호 출력하기. __FILE__, __FUNCTION__, __LINE__ 등의 전처리 매크로를 알아보자.

[C, C++ 목차 바로가기]

안녕하세요~~!

양햄찌 블로그 주인장 입니다.

 

오늘은 로그 파일 만들때 단골로 사용되는 매크로들을 알아보아요.

해당 매크로들은, 호출된 시점에서 파일명과 함수명 그리고 라인명을 알려주는 기능을 수행합니다.

호출된 녀석의 위치와 정보를 아는 것은 중요하다~

■ ERROR TRACKING

어느 파일, 어느 함수에서 해당 로그가 찍혔는지 아는 것은 디버깅에 매우 중요합니당. 

에러가 발생했을 경우, 어디까지 정상이었다가 어디부터 걸렸는지 쉽게 파악할 수 있어요.

 

■ SOURCE FLOW

에러가 났을 때 뿐만 아니라, 소스가 매우 길고 복잡할 경우, 이런 로그 정보들을 차례대로 따라가면 로직 FLOW를 쉽게 이해하는데 도움이 됩니다. 어디 모듈 다음엔 어느 모듈이 호출되고,, 어떤 기능을 하는 함수 다음엔 이 함수가 실행되고.. 전체적인 관점에서 흐름을 볼 수 있어요. 

 

■ CORRECTING 

또 수정할때도 용이합니다. A가 출력되는 부분에서 A뿐만 아니라 B,C도 같이 출력하게끔 추후 변경하고 싶을 때, 해당 파일명과 함수를 바로 알 수 있으니까 수정해야할 부분을 손쉽게 찾을 수 있어요. 

이런 역할을 수행하는 매크로들에 대해서 알아봅시다~!

매크로 소개

__FILE__  

: 해당 매크로가 호출된 파일명을 담고 있습니다.

__FUNCTION__ 

: 해당 매크로가 호출된 함수명을 담고 있습니다.

__LINE__

: 해당 매크로가 호출된 라인번호를 담고 있습니다.

 

끝입니당 간단하죠?

 

테스트를 위한 아주 간단한 코드를 C언어로 작성해보았어요. 

#include <stdio.h>
#define print_func() printf("FILENAME: %s, FUNCNAME :%s, LINENO :%d\n"\
							,__FILE__, __FUNCTION__, __LINE__)
void afunc();
void bfunc();
int main()
{
	afunc();
	bfunc();
	return 0;
}
void afunc()
{
	print_func();
}
void bfunc()
{
	print_func();
}

이를 실행해보면

비주얼스튜디오에서 실행했을 때

__FILE__결과: "c:\users\jhnya\source\repos\test1\test1\source.cpp"

__FUNCTION__ 결과: afunc / bfunc

__LINE__ 결과: 15 / 19 

이렇게 비주얼스튜디오에서는 __FILE__이 파일 경로까지 다 포함해서 보여주고 있어요.

리눅스 

반면 리눅스 gcc 컴파일러에서는 오로지 파일명만 보여줍니다.

이렇듯 컴파일러별로 매크로 출력 결과에 대한 차이가 있으니, 한 번쯤 확인하고 코드를 작성하기~

사용시 주의할점

■ 일부 컴파일러에서는 _FILE_이 절대경로를 반환해주는 경우가 있습니다. 

 일부 컴파일러에선 __FUNCTION__이 class name을 포함하는 경우도 있습니다.

 로그 출력 함수를 만들겠다고, 로그 함수 내에서 이 매크로들을 직접적으로 사용하면 안됩니다.  

'a함수'에서 로그찍는 함수를 호출했을 때, 로그에 'a함수'라고 찍혀 아 a함수가 실행중이구나~ 이걸 아는게 우리의 목표인데, 이 매크로를 로그함수 내에서 직접적으로 사용했을 경우는 대상이 'a함수'가 아니라 '로그함수'가 됩니다. 매크로를 호출하는 애가 매크로값이 되기 때문이야요.

[예시 소스코드]

1. #include <stdio.h>
2. void printlog(); 
3. void afunc(); void bfunc();
4. int main()
5. {
6. 	afunc();
7. 	bfunc();
8. 	return 0;
9. }
10. void printlog()
11. {
12. 	printf("FILENAME: %s, FUNCNAME :%s, LINENO :%d\n", __FILE__, __FUNCTION__, __LINE__);
13. }
14. void afunc()
15. {
16. 	printlog();
17. }
18. void bfunc()
19. {
20. 	printlog();
21. }

afunc가 실행중일 때 로그를 찍으니까, 실행중인 함수는 afunc, 실행중인 라인은 15 이렇게 찍히게 하고 싶었던건데 실제 수행을 해보면,

함수 이름은 printlog가 나오고 라인은 12이 나오네요! 왜냐 이 매크로를 호출한 함수는 실질적으로 printlog이고 12번째 라인에 있기 때문입니다. 이를 우리가 의도한 것처럼 변경해주려면 

#include <stdio.h>
void printlog(const char* filename, const char* funcname, const int lineno); 
void afunc(); void bfunc();
int main()
{
	afunc();
	bfunc();
	return 0;
}
void printlog(const char* filename, const char* funcname, const int lineno)
{
	printf("FILENAME: %s, FUNCNAME :%s, LINENO :%d\n" , filename, funcname, lineno);
}
void afunc()
{
	printlog(__FILE__, __FUNCTION__, __LINE__);
} 
void bfunc()
{
	printlog(__FILE__, __FUNCTION__, __LINE__);
}

실제 의도한 함수에서 매크로를 사용한 후 로그 함수에 인자로 넘겨줘야 해요.

결과를 보면 우리가 원하는대로 의도된 것을 확인할 수 있습니다.

 

■ 가변인수 조합 활용하면 좋음

근데 위의 예시의 경우, 로그 함수 호출시마다 매번 __FILE__, __FUNCTION__, __LINE__ 를 일일이 작성해서 넣어줘야 하는게 여간 귀찮은게 아니예요. 자주 사용하는 함수는 단순할 수록 편리하겠죠.

또 내가 확인하고 싶은 정보를 같이 담아 출력해줄 수 있어야 진정한 로그함수에 가깝다 할 수 있어요.

가변인수를 사용하면 둘 다 잡을 수 있습니다.

#include <stdio.h>
#include <stdarg.h>
#define printlog(fmt, ...) printlog_(__FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
void printlog_(const char* filename, const char* funcname, const int lineno, const char* fmt, ...);
void afunc(); void bfunc();
int main()
{
	afunc();
	bfunc();
	return 0;
}
void printlog_(const char* filename,const char* funcname, const int lineno, const char* fmt, ...) {
	va_list ap;
	va_start(ap, fmt);
	printf("[FILENAME: %s, FUNCNAME :%s, LINENO :%d] ", filename, funcname, lineno);
	vprintf(fmt, ap);
	va_end(ap);
}
void afunc()
{
	int num = 3;
	printlog("num: %d\n", num);
}
void bfunc()
{
	int num = 5;
	printlog("num: %d\n", num);
}

결과

가변 인수 사용법이 궁금하신 분들은 자세한 사항은 아래 포스팅을 참고해주세요

https://jhnyang.tistory.com/293

 

[C,C++] 가변인자 함수의 사용(va_start, va_arg, va_list등등) 함수에 불특정 여러개의 인자를 넘기고 싶�

[C, C++ 프로그래밍 강좌 목차] 안녕하세요~ 양햄찌 주인장입니다. 오늘은 오랜만에 프로그래밍 언어에 관련된 포스팅을 들고왔어요. 오늘의 주제 포스팅을 들어가기 전 'C++의 오버로딩'에 대한 ��

jhnyang.tistory.com

오늘도 수고많으셨어요. 도움이 되는 포스팅이였다면 공감 살포시 어떤가요??

응원은 정보공유에 큰 힘이 됩니다 :) 다음 포스팅에서 또 봐요~