본문 바로가기

C언어9

2-1. C언어 스마트포인터 C언어에서 메모리 관리는 개발자를 따라다니면서 괴롭히는 문제이다. 그 중에서 할당한 메모리를 올바른 때에 회수하는 일은 숙련된 개발자라도 실수를 할 수 있다. 실수를 하지 않는다고 하더라도, 할당된 메모리를 해제하고 이로인해 댕글링 포인터 이슈가 없게 하는 것은 귀찮은 일임에 틀림없다. 이번 포스트에서는 GCC 확장 기능으로 스마트포인터를 사용하는 방법과 이를 매크로로 등록해서 편하게 활용하는 바법에 대해서 살펴보려 한다. 스마트포인터란?(C++의 스마트포인터) GCC cleanup 속성 스마트포인터 매크로로 제작 (및 경고 문구 회피) 1. 스마트포인터란?(C++의 스마트포인터) 동적할달된 메모리를 매번 해제해야 하는 불편을 회피하기 위해서 C++에는 스마트포인터를 제공한다. 스마트 포인터는 힙에 동적.. 2022. 1. 14.
2. 중첩된 Goto 문을 이용한 에러 핸들링 앞선 포스트에서 Goto 문을 이용해서 try-catch와 유사하게 에러 핸들링을 하는 방법에 대해 살펴보았다. 이번 포스트에서는 Goto 문 여러개를 이용해서 단계별로 에러 핸들링을 하는 방법에 대해 다뤄보려 한다. 특정 함수 안에서 작업 A, B, C가 이뤄진다고 가정해 보자. 이 작업들은 완료가 된 이후 반드시 정리가 되어야 자원 낭비(e.g. 메모리릭)가 발생하지 않는다. 그렇다면 함수를 빠져나가기 전에 A, B, C 작업은 모두 정리가 되어야 한다. C언어에서 If를 사용해서 각 작업을 정리하는 프로세스를 그림으로 그리면 아래와 같다. 위 그림에서 보이는 문제는 크게 두 가지이다. 불필요한 코드 중복 발생 휴먼 에러에 의한 버그 발생 확률 증가 불필요한 코드 중복 발생은 작업 정리 프로세스들이 .. 2021. 12. 30.
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.
2. 메모리 누수 없는 C언어 프로그래밍 (3/3) - 레퍼런스 카운트 2부 이전 포스트들에서 다룬 규칙을 다시 한 번 더 확인해보자. (규칙1) 가능하다면 메모리 할당과 해제는 한 코드 블록 안에서 한 번만 (규칙2) 메모리 할당과 해제가 한 블록 이내에서 이뤄질 수 없다면 레퍼런스 카운트를 활용 이전 포스트에 이어지는 내용으로 이전 포스트를 읽지 않았다면 먼저 읽기를 강력히 권한다. ("2. 메모리 누수 없는 C언어 프로그래밍 (2/3) - 레퍼런스 카운트 1부" (www.kernelpanic.kr/35)) 이전 포스트에서는 규칙 2를 구현하는 간단한 방법에 대해서 살펴보았다. 이번 포스트에서는 앞에서 살펴본 구현의 취약점을 살펴보고 코드를 좀 더 정교하게 구현하는 방법에 대해서 살펴본다. 레퍼런스 카운트가 제대로 해제되지 않는 경우 앞서 우리는 레퍼런스 카운트(이하 rc)를.. 2021. 5. 13.
2. 메모리 누수 없는 C언어 프로그래밍 (2/3) - 레퍼런스 카운트 1부 앞선 포스트에서 C언어에서 메모리 누수를 피할 수 있는 두 가지 규칙을 소개하고, 규칙1 "가능하다면 메모리 할당과 해제는 한 코드 블록 안에서 한 번만"에 대해서 다뤘다. (www.kernelpanic.kr/34) 규칙1은 간단하고 강력하지만 규칙1을 적용할 수 없는 예외적인 상황들이 있다. 이 경우에 사용 가능한 방법이 규칙 2 "메모리 할당과 해제가 한 블록 이내에서 이뤄질 수 없다면 레퍼런스 카운터를 활용"이다. 이번 포스트에서는 어떤 경우에 규칙1을 적용할 수 없는지, 그리고 레퍼런스 카운터를 활용하는 방법에 대해서 다루도록 한다. (규칙1) 가능하다면 메모리 할당과 해제는 한 코드 블록 안에서 한 번만 (규칙2) 메모리 할당과 해제가 한 블록 이내에서 이뤄질 수 없다면 레퍼런스 카운트를 활용 .. 2021. 5. 5.
1. C언어 메모리 관리의 어려움 (2/2) - C언어 메모리 문제 유형들 본 포스트에서는 C언어에서 쉽게 겪을 수 있는 메모리 문제들의 유형을 다룬다. 만약 C언어 메모리 구조에 대해서 잘 알지 못한다면, 앞선 포스트(www.kernelpanic.kr/32)를 먼저 보고오자. C언어 메모리 구조 및 어떤 종류의 메모리 문제 유형들이 있는지 잘 안다면 다음 포스트(www.kernelpanic.kr/34)로 넘어가면 된다. 이번 주제에서 C의 모든 메모리 문제를 해결할 수 있는 솔루션을 제시하지는 않는다. 그럴수도 없다. 다만 메모리 릭과 댕글링 포인터 이슈를 회피하는 테크닉에 대해서 다룰 예정이다. 따라서 메모리 릭과 댕글링 포인터 문제 유형에 대해서 확인하고 가면 된다. 1.2.1 메모리 릭(Memory Leak) 메모리 릭은 프로그램이 불필요한 메모리를 계속 점유하는 현상이.. 2021. 4. 28.
1. C언어 메모리 관리의 어려움 (1/2) - C언어 메모리 구조 포인터는 C언어의 가장 큰 강점이자 우리를 늘 메모리 관련 문제로 괴롭히는 큰 위험요인이다. 많은 좋은 프로그램들이 C언어의 포인터 기교를 사용해서 엄청난 메모리 / 성능상의 이득을 얻었다. 몇년도 전이지만, 아직도 리눅스 커널과 리눅스의 tcp/ip 스택에서 C언어 포인터를 활용한 것을 처음 봤을때의 신선한 충격이 생생하다. 훌륭한 프로그래밍 언어들이 많이 나왔지만 여전히 C의 포인터만큼 HW 직관적이고 강력한 개념은 없는 것 같다. 그러나 동시에 포인터는 원인을 찾기 어려운 버그들을 만들어 내곤 한다. 특히 어떤 버그들은 원인을 찾고서도 고치기가 몹시 난해한 경우들도 있다. 이는 훌륭한 프로그램에서도 예외가 아니다. 모질라 재단은 파이어폭스의 메모리 누수 문제로 수 년간 씨름하다가 결국 C++로 개발.. 2021. 4. 27.
1-1. 객체지향 C언어? (클래스, 다형성) 객체지향이란? C언어의 객체지향이라는 주제로 이야기를 하려면, 우선 "객체지향"이란 무엇인지부터 짚고 넘어가야 한다. 나는 개인적으로 "클린 아키텍쳐"에서 말하는 객체지향 개념을 선호한다. 마틴 파울러는 클린 아키텍쳐에서 객체지향을 "객체지향이란 다형성을 이용하여 전체 시스템의 모든 소스코드 의존성에 대한 절대적인 제어 권한을 획득할 수 있는 능력"이라고 정의한다. 이 말을 장황하게 풀어쓰면 다음과 같다. 객체지향을 활용하면 #1. SW 세부사항들이 핵심사항을 의존하도록 구성하고, #2. 각 SW 모듈간 의존성은 최소화하며, #3. 인터페이스 등을 통해 SW 다형성을 확보하여 #결론. 시스템의 개발/수정/유지보수의 용이성을 크게 높을 수 있다. 이 정의대로면 C언어로도 충분히 객체지향적인 코드를 짤 수 .. 2020. 8. 25.