본문 바로가기

모던 C 언어16

2-1. C언어 스마트포인터 C언어에서 메모리 관리는 개발자를 따라다니면서 괴롭히는 문제이다. 그 중에서 할당한 메모리를 올바른 때에 회수하는 일은 숙련된 개발자라도 실수를 할 수 있다. 실수를 하지 않는다고 하더라도, 할당된 메모리를 해제하고 이로인해 댕글링 포인터 이슈가 없게 하는 것은 귀찮은 일임에 틀림없다. 이번 포스트에서는 GCC 확장 기능으로 스마트포인터를 사용하는 방법과 이를 매크로로 등록해서 편하게 활용하는 바법에 대해서 살펴보려 한다. 스마트포인터란?(C++의 스마트포인터) GCC cleanup 속성 스마트포인터 매크로로 제작 (및 경고 문구 회피) 1. 스마트포인터란?(C++의 스마트포인터) 동적할달된 메모리를 매번 해제해야 하는 불편을 회피하기 위해서 C++에는 스마트포인터를 제공한다. 스마트 포인터는 힙에 동적.. 2022. 1. 14.
1. 로그 출력 시 유용한 매크로들 (__func__, __LINE__, __FILE__, __DATE__, __TIME__) printf로 로그를 출력하다보면 로그가 좀 더 풍부했으면 좋겠다는 생각들을 종종 하게 된다. 예를 들어서 현재 어떤 파일에서 몇번째 라인에 에러가 발생했는데, 특정 모듈은 언제 빌드가 되었는지 등등을 말이다. 다음 소개하는 매크로는 로그를 더욱 풍부하게 만들어 줄 수 있는 매크로 들이다. 매크로 타입 내용 __func__ 문자열 (%s) 매크로가 호출된 함수를 출력한다. __LINE__ 정수 (%d) 매크로가 호출된 라인을 출력한다. __FILE__ 문자열 (%s) 매크로가 출력된 파일을 출력한다. (빌드한 위치 기준) __DATE__ 문자열 (%s) 빌드가 이뤄진 날짜를 출력한다. __TIME__ 문자열 (%s) 빌드가 이뤄진 시간을 출력한다. 어렵지 않은 내용이라 금방 이해할 수 있다. 아래는 위 .. 2022. 1. 3.
2. 중첩된 Goto 문을 이용한 에러 핸들링 앞선 포스트에서 Goto 문을 이용해서 try-catch와 유사하게 에러 핸들링을 하는 방법에 대해 살펴보았다. 이번 포스트에서는 Goto 문 여러개를 이용해서 단계별로 에러 핸들링을 하는 방법에 대해 다뤄보려 한다. 특정 함수 안에서 작업 A, B, C가 이뤄진다고 가정해 보자. 이 작업들은 완료가 된 이후 반드시 정리가 되어야 자원 낭비(e.g. 메모리릭)가 발생하지 않는다. 그렇다면 함수를 빠져나가기 전에 A, B, C 작업은 모두 정리가 되어야 한다. C언어에서 If를 사용해서 각 작업을 정리하는 프로세스를 그림으로 그리면 아래와 같다. 위 그림에서 보이는 문제는 크게 두 가지이다. 불필요한 코드 중복 발생 휴먼 에러에 의한 버그 발생 확률 증가 불필요한 코드 중복 발생은 작업 정리 프로세스들이 .. 2021. 12. 30.
1. Goto를 사용한 에러핸들링 프로그래밍을 하다보면 발생 가능한 에러들에 대해서 신경을 써야 한다. 버그는 신중한 개발자가 좋은 코드를 짠다면 최소화 할 수 있는 반면, 에러는 좋은 코드에서든 나쁜 코드에서든 발생한다. 결국 우리는 에러가 발생할 수 있다는 사실을 받아들이고, 이를 어떻게 처리할 지 생각해야 한다. 다음은 흔히들 마주칠 수 있는 에러들의 예시이다. 파일 열기 파일 입출력 소켓 통신 메모리 할당 C언어 이후에 개발된 언어들은 대부분 Try-Catch 혹은 이와 유사한 구문을 지원한다. Try-Catch 문에 익숙하지 않다면 아래 Java 프로그램의 예시를 살펴보자. 더보기 다음은 파일을 열고, 내용을 한줄씩 출력하는 Java 프로그램이다. import java.io.BufferedReader; import java.io.. 2021. 12. 26.
3-2. GLib의 자료구조들 (해쉬 테이블 - GHashTable) 본 포스트를 이해하려면 해쉬 테이블에 대한 사전 지식이 필요하다. 만약 해쉬 테이블이 무엇인지 모른다면 먼저 해당 내용들에 대해서 구글링을 해 보자. 해쉬 테이블은 데이터를 Key-Value 쌍으로 관리하기 위한 자료구조이다. 하나의 Key에 하나의 Value만 저장될 수 있다. 아래는 GHashTable로 데이터 삽입, 삭제, 조회, 순회를 하는 간단한 예제이다. #include #include #include // typedef void* gpointer; // HashMap을 순회하면서 호출되는 콜백함수 static void print_film(gpointer key, gpointer value, gpointer user_data) { char *film = (char*)key; char *coun.. 2021. 12. 18.
3-1. GLib의 자료구조들 (링크드 리스트 - GList) 본 포스트를 이해하려면 링크드 리스트에 대한 사전 지식이 필요하다. 만약 링크드 리스트가 무엇인지 모른다면 먼저 해당 내용들에 대해서 구글링을 해 보자. 링크드 리스트는 자료구조책 초반부에 나오면서도 프로그래밍을 하다보면 정말 많이 사용하게 되는 자료구조이다. 개인적으로는 아마 GLib의 모든 자료구조 중에 가장 많이 사용하는 자료구조이다. 백문이불여일견으로 우선 GList로 간단히 데이터 삽입, 삭제, 순회를 하는 예제 코드를 보고, GList를 어떻게 사용하면 되는지 알아보자. #include #include // typedef void* gpointer; // 리스트를 순회하면서 호출되는 콜백함수 static void print_film(gpointer data, gpointer user_data).. 2021. 12. 17.
2. C언어의 STL, GLib ※ glibc와 혼동하지 말자. glibc(gnu c library)는 gnu에서 만든 C 표준 라이브러리이다. 반면 GLib는 gnome 재단에서 만든 서드파티 라이브러리이다. GLib는 C언어 프로그램 개발을 돕는 라이브러리이다. C언어가 개발된지 어느덧 50년이 다 되어가는 만큼 지원하는 기능이 제한적이다. 대표적으로 C언어는 표준 자료구조, 클래스, 추상화된 파일 입출력 라이브러리 등 현대 언어에서 지원하는 기능들이 빠져있다. GLib는 현대 언어들이 제공하는 고수준 기능들을 C언어에서도 사용할 수 있도록 돕는 라이브러리이다. 2.1 GLib란? 공식 GLib 문서에서는 GLib에 대해 아래와 같이 설명하고 있다. GLib is a general-purpose, portable utility li.. 2021. 12. 17.
1. C언어의 제네릭 자료구조들, 하지만 2% 부족한 오늘날 주로 사용되는 언어들 중에서 C언어의 생산성은 낮은 편이다. C언어가 생산성이 낮은 이유는 여러가지가 있겠다. 개인적으로 생각하는 C언어가 생산성이 낮은 이유들은 다음과 같다. 문법적으로 Class를 지원하지 않는다. 예외처리방법이 일관되지 않고 귀찮다. 포인터 관련 메모리 관리가 어렵다. STL과 같은 제네릭 자료구조를 지원하지 않는다. 이번 주제를 통해서는 C언어의 생산성을 크게 높일 수 있는 방법 - STL과 같은 제네릭 자료구조 - 를 사용하는 방법에 대해서 다룰 예정이다. 주된 내용은 glib의 자료구조를 사용하는 방법에 대해서 다룰 예정이다. 이번 포스트에서는 준비 운동 느낌으로 C언어에서 (glib를 제외한) 사용 가능한 제네릭 자료구조들과 한계점들에 대해서 살펴보자 커널 제네릭 자료.. 2021. 5. 22.
3. C언어 레퍼런스 카운팅 방법의 한계 및 팁 들 본 포스트는 https://www.kernelpanic.kr/35와 https://www.kernelpanic.kr/36를 읽었다는 것은 전제로 작성되었다. 앞의 두 포스트를 먼저 읽고 오기를 바란다. 레퍼런스 카운팅 방법의 한계 레퍼런스 카운팅은 C언어에서 쉽고 효율적으로 메모리 관리를 할 수 있는 방법이다. 이 방법을 사용하면 대부분의 메모리 누수 관련 버그를 회피할 수 있지만 회피할 수 없는 누수도 있다. 순환참조(Circular Reference) 이슈이다. 순환참조는 둘 혹은 그 이상의 객체가 서로를 참조하는 상황이다. 예를 들자면 A 객체가 B 객체를 참조하고, B 객체가 A 객체를 참조하는 상황이다. 조금 꼬아본다면 A 객체가 B 객체를 참조하고, B 객체가 C 객체를 참조하는 상황에서 C .. 2021. 5. 21.