일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Listen
- 리눅스
- 노트북 배터리 교체
- ubuntu
- 인천
- 괌
- 칼국수
- 다수 클라이언트
- hostkeyalgorithms
- 괌여행
- xshell4
- gdb tip
- thread pid
- 인화여고
- core file
- linux
- IPv6
- 출력
- ubuntu22.04
- vcore
- host key
- 옛날 탕수육
- 껍질없는
- whatis
- C
- vi
- kdumo
- 노트북 정보
- spacse
- 디버깅
- Today
- Total
극히 개인적이고 극히 대단하지 않은
C 디버깅용 로그 출력할 때, 자동으로 함수이름과 라인번호 출력하기 본문
귀차니즘의 극을 달리다가 드디어 정리한다.
뭐 그리 중요하거나 대단한 기술은 아니지만, 더 머리가 굳어가기 전에 남겨두는 게 맞을 것 같아서...
코드를 작성하고 디버깅을 하다보면, 코드 어디 쯤 실행이 되고 있는 것인지 확인하는 가장 좋은 방법이 로그를 찍어보는 것이다. 그런데, 간혹 다른 사람의 코드를 디버깅하다보면 'return NOK!' 라는 출력이 있어 여기 쯤 문제가 있겠구나 하고 추정을 하게되고 'return NOK!' 라는 문자열을 소스에서 찾아보게 되는데, 'return NOK!' 라는 문자열이 이런 저런 소스에 분산되어 한 200군데에 있다면, 정말 짜증이 나지 않을 수 없다.
개인적으로 간단하게 로그의 위치를 확인하기 위해서는 잘 알려진 방법인 __func__와 __LINE__ 매크로를 사용하는 방법을 쓰곤한다. (__func__와 __FUNCTION__의 차이점을 굳이 확인하고자 하는 포스팅이 꽤 있는데, 20년간 코딩을 하면서 그 둘을 굳이 구분해야할 상황을 한 번도 접하지 않았으므로 따지지 말자.)
printf ("<%s:%d> return NOK!\n", __func__, __LINE__); |
코드 중간중간에 위와 같은 형식으로 출력을 하게되면 같은 출력이더라도 출력이 발생하는 함수명과 라인번호가 함께 출력이 되기 때문에 따라가기가 영 쉽다.
그런데, 디버깅의 양이 방대해지거나 조밀하게 로그를 넣어야 하는 경우에는 반복되는 __func__와 __LINE__ 을 입력하는 데에도 상당한 시간을 들이게되고 짜증이 나는 일이 되기도 한다.
그래서, 항상 해야지 해야지 하면서도 게을러서 하지 못했던, __func__와 __LINE__ 을 일일히 입력하지 않아도 되도록 함수와 라인정보를 출력하는 라이브러리의 베이스형을 만들고 여기에 그 흔적을 남긴다.
아래는 헤더 파일이고 (log.h 정도로 이름지으면 될 듯)
#define Log(fmt, args...) LogPrint(__LINE__, __func__, fmt, ## args) int LogPrint (const int line, const char *func, const char *format, ... ); |
그리고 라이브러리 소스 파일 (역시 log.c 정도로 이름지으면 될 듯)이다.
int LogPrint (const int line, const char *func, const char *format, ... ) { int charsNo; va_list ap; time_t *cur; struct tm *now, rt; struct timeval tv; gettimeofday(&tv, NULL); cur = (time_t *)&(tv.tv_sec); now = localtime_r(cur, &rt); printf( "[%02d:%02d:%02d.%03d] | <%s:%d> ", now->tm_hour, now->tm_min, now->tm_sec, (int)(tv.tv_usec/1000), func, line ); va_start(ap,format); charsNo = vprintf(format,ap); va_end(ap); return charsNo; } |
log.a라는 라이브러리로 만든 후, 임의의 소스에 Log ("블라블라...\n"); 를 호출하면 예쁘게
위와 같이 출력이 된다.
위의 예시에서는 시간정보도 같이 출력하도록 했는데, 소스를 수정하여 시간정보까지 필요없다면 빼버리거나, 파일명 정보(__FILE__ 매크로 이용)를 추가하는 등의 변형도 얼마든지 가능.
한번 쯤 아래와 같이 바로 Log 함수를 코딩했다가 낙심한 경험이 있는 개발자들에게 도움이 되기를...
printf( "[%02d:%02d:%02d.%03d] | <%s:%d> ", now->tm_hour, now->tm_min, now->tm_sec, (int)(tv.tv_usec/1000), __func__, __LINE__ ); |
'20년차 개발자' 카테고리의 다른 글
리눅스에서 thread의 pid를 확인하는 코드 (0) | 2022.10.27 |
---|---|
요긴한 gdb 명령들 (0) | 2021.05.20 |
vi 에디터로 hex모드로 에디팅 시 컬럼 수 늘이기 (0) | 2020.04.22 |
strace 로 프로세스 트레이스 할 때 출력문의 길이가 짧아서 곤란할 때. (0) | 2020.04.13 |
Device type별 dmidecode (0) | 2020.03.11 |