별빛의 낙하지 :: '분류 전체보기' 카테고리의 글 목록



  개정판 이전의 책을 학교 도서관에서 잠깐 본 뒤로 이 책을 잊고 있었다.

그러다가 최근 기회가 되어서 다시 이책을 보게 되었다. 기존에 나온 국내 도서 중에서 유닉스/리눅스 계열의 프로그래밍 유틸리티들을 정말 많이 설명하고 있다고 평가하고 싶다.


 책의 전반적인 내용들은 주로 개발과 관련된 내용으로써 컴파일과 링킹, 디버깅, 에디트, 빌드를 비롯하여 버전관리 프로그램까지 유닉스/리눅스 환경에서 주로 쓰이는 굵직굵직한 유틸리티들을 다루고 있다. 


 책의 용도는 짬짬히 코딩하다가 참고하는 용도나 컴파일러, 링킹, 그리고 실행파일 포맷, 디버깅에 대해서 기본적으로 알아야 할 것에 대해서 학습하고 싶은 사람들에게 적당한 것 같다. 유닉스 리눅스 계열의 유틸리티 도서가 윈도우에 비해서 상대적으로 별로 없어서 그런지 같은 출판사의 윈도우 유틸리티 책 보다 좀 더 괜찮다는 느낌이 든다. 또한 책의 중간중간에 저자가 터미널로 실행한 실행화면이 포함되어 있어서 보다 의미전달이 명확하다는 느낌이다.


 개인적으로 책의 설명중에서 가장 유익했던 내용은 gcc나 gdb와 관련된 내용이었다. 책의 저자가 과거에 개발했던 컴파일러 개발과 관련된 경험 덕분인지, gcc의 동작원리나 사용법, 그리고 옵션에 대해서 정말 잘 알고 있다는 느낌을 받았고, 자연스럽게 이어지는 컴파일, 링킹 과정에서의 세세한 동작들,  그리고 시스템 프로그래밍의 전반적인 부분에서 적절한 설명과 예시가 들어가 있었다는 점에서 유익한 내용이었다.


 가령 예를 들어서 컴파일 과정에서 생성되는  gimple 트리를 확인하는 부분이 매우 흥미로웠다.  for 문이 컴파일되면서 goto문으로 이루어진다는 사실 말이다.  또한 그 뒤에 나오는 ssa파일을 만드는 단계 또한 컴파일러의 동작 결과를 직접적으로 느낄 수 있는 지면을 제공해줬다는 점에서 매우 고마웠다.


 책을 읽으면서 아쉬운 부분은 172page에 나오는 함수의 원형과 관련된 설명이다.  함수의 원형이 먼저 선언이 되어 있어야 함수 호출이 가능한 것처럼 설명이 되어 있는데, 대부분의 C언어 컴파일러에서는 함수의 원형이 선언이 되어 있지 않아도 암시적으로 호출이 가능하게끔 되어 있다.  필자도 그것에 대해서 잘 알고 있는 듯 하지만, 뒤에 가변인자와 관련된 설명에 있어서 예시를 들은 printf의 사례는 좀 부적절했다고 생각을 한다.  가변인자 함수라고 해도 함수의 원형이 없어도 충분히 호출이 가능하기 때문이다.


 또한 463page에 언급이 된  "모든 프로세스는 실행될 때 위와 같은 4기가 바이트의 가상 주소 공간을 가진다." 라는 내용은 어디까지나 32bit 운영체제에서 통용되는 이야기이다. 이 부분은 누구나 다 아리라고 판단이 되지만 약간 잘못 받아들여질 여지가 있지 않나 싶다. 필자도 알고 있었겠지만 약간의 보충 설명이 있었으면 더 좋았을 거라고 생각한다.


  465page 이후는 주로 스택프레임과 관련된 내용이 설명이 되어 있다.  살펴보니 c의 함수 호추 규약인 cdecl 을 기준으로 맞춰져 있다.  엄연히 이야기해서 thiscall, fastcall 등과 다른 약간 다른 방식으로 스택프레임이 만들어지기 때문에 설명을 할때 어느정도 언급이 필요하지 않을까 생각한다.  그리고 함수 스택프레임을 이루는 과정에 있어서 프롤로그와 에필로그에 대한 설명 또한 부족하다.

 

  에디트는 주로 vim을 다루고 있으며, 따라서 vim을 주로 쓰는 사람들에게는 충분히 유용한 정보가 담겨 있다고 생각한다. 나의 경우 팁이 매우 유용하게 느껴졌다.


  책을 읽으면서 저자에게 책을 써줘서 굉장히 감사하다고 말하고 싶다.  간만에 비빔밥처럼 필요한 영양이 골고루 들어 있다는 느낌이랄까.  


  



 C를 처음 접한지가 10년이 다 되가는 입장에서 책을 읽는 내내 감회가 새로웠다.(처음 읽은 C언어 책은 고등학교 1학년 때 읽었던 알기쉽게 해설한 C였다.)  단도직입적으로 이야기 해서 기존의 국내 서적 대부분이 C의 문법적인 측면과 그에 맞는 예제들을 제시하는 측면에서 다루고 있어서 소스 파일이 컴파일러, 링커를 어떻게 거치는지를 비롯하여 정적 링킹, 동적 링킹, IPC  등 시스템과 관련된 내용을 잘 제시하지 못한다.


 그러한 측면에서 헤드 퍼스트 C는 가뭄에서 단비와 같은 책이다. 문법적인 설명보다 실용적인 측면, 그리고 유닉스/리눅스 환경에 친숙한 도구들을 사용하여 컴파일러, 링커의 대략적인 동작 원리, 링크를 만드는 과정, valgrind로 메모리 누수를 측정하는 방법, 프로세스를 만들고, 통신하고, 스레드를 만들고 동기화 하는 것들을 총 망라했기 때문이다. 


  적어도 국내의 입문서들의 책을 읽었을 때 독자들은 컴파일러와 링킹의 과정을 제대로 이해할 수 있을까 라는 의구심이 들때가 있다.  또한 파이프, 프로세스, 스레드와 관련된 측면에서 다 같이 설명하지 못하는 것은 대부분의 책에서 다루는 환경의 근간이 윈도우라는 점이 없지 않아 있다고 생각한다.  그러한 측면에서 이 책은 리눅스/유닉스 환경에서 gcc를 이용하는 방법을 알려 주고 있고, 책의 내용을 하나씩 따라가다보면 적어도 앞으로 어떤 도구를 이용하여 공부해야 하는지 알 수 있다.(다른 점들은 윈도우와 맥 환경을 비교해서 언급하기도 한다.) 단점은 독자가 리눅스/유닉스 환경 또는 커맨드 라인에  친숙하지 않다면 적응하기가 조금 힘드리라 예상된다.


  전반적인 책의 구성에 있어서 배치는 필요에 의한 인과관계순이다.  예를 들어 표준 입출력을 설명하고, 여러개의 입출력을 둘 경우에는 어떻게 될것인가에서 파일이 등장한다거나, 힙할당이 나온다음에 valgrind가 나오는 등이다. 번역 상태는 나름대로 훌륭하고, 문법에 있어서 겉절이(?)들은 뒤에 부록으로 남겨놨으니 부록부터 읽어도 문제가 없다.  개인적으로 훌륭했던 것은 머니머니해도 QA부분이다. break문에 대한 설명이나. COW에 대해 언급, valgrind에 대한 설명 등이다.(이건 저자가 외국인이기에?)


  이 책의 최대 단점은 무엇일까?  다른 책과 비교해서 탄탄하게 문법을 배운다는 느낌이 약하다는 것?

그리고 문법을 이해하기 위한 예제가 적어서 연습하기가 그렇다는 것? 정도


  끝으로 헤드퍼스트 시리즈와 마찬가지로 이 책을 읽는 방법은 순서대로 따라가면 된다.  한 책을 통해서 무언가 개념을 이해하기에는 입문자에게는 중간 중간에 버거운 지점이 있겠지만, 이 책을 읽어본 결과 설명이 나름 잘 되어 있고, 부족한 설명이나 의문은 챕터별로 끝에 QA란에 잘 적혀 있다. 내가 본 헤드 퍼스트 시리즈중에서 디자인패턴 다음으로 실용적이었던 것 같다.






[리뷰] 만들면서 배우는 인터프리터

리뷰 2012. 11. 24. 21:06 Posted by byulbit



   

  전산을 전공한 학생이라면, 대학교시절 내에 가져보는 만들어보고 싶은 로망(?)이 있을 것이다.

사람마다 다르지만 주로 운영체제와 컴파일러를 꼽는다.

문제는 둘 다 만들기가 굉장히 힘들다.   간단히 만들어보려고 해도 공부해야 할 것들이 많기 때문이다. 

그러한 점에서 컴파일러는 아니지만, 쉽게 시도해본다는 측면에서 이 책이 나온 것은 정말 좋다고 생각한다.

  인터프리터 소스(BBI)가 생각보다 분량이 적고, C를 이전에 공부하였다면,  쉽게 시도할 수 있다.( 물론 STL의 stack이 나와서 STL 공부해야 하는거 아니냐? 라고 반문할 수 있지만, 부록으로 설명하고 있는 정도만 이해해도 이책의 소스를 이해하는데에 전혀 문제가 없다.)


  책의 아쉬운점은 Step by Step이 아니라는 점이다.   따라서 전반적으로 인터프리터에 필요한 요소들을 먼저 챕터로 세분화하여 간략히 설명하고, 마지막에 소스 부록(완성체)이 실리는 구성이라서 맨땅에서 하나씩 추가하는 식으로 공부하는 성취감(?)을 얻을 수 없다.  소스코드(완성체)를 먼저 돌려보고, 궁금한 챕터나 관련 챕터를 찾아서  챕터별 예제나 소스를 분석하는 것이 제격에 맞다. (책을 읽으면서, 이런 책은 가이딩(guiding)이 필요해서 나온 책인 것 같은데 뭔가 가이딩이 약하다는 느낌을 받았다.)


  또한 분석을 하려면, 구성 요소에 대해서 배경지식이 되는 것에 대한 이해가 필요하다.  하지만 이 책은 얇은게 장점... 따라서 사전에 인터프리터에 대한 어느정도 배경 지식이 있는 상태가 아니라면 집요하게 조모조목 짚고 넘어가지 않는다면,  설명이 짧아서 자칫 이해가 안될 수 있다. 


  그럼에도 이 책의 진가는 넘사벽이라고 생각되었던 것에 대한 통념을 깼다는 점에서 괜찮은 책이라고 생각한다.( 물론 이건 컴파일러가 아니다.  그래서 어렵지 않다고 할 수 있지만, 사실  인터프리터도 만들기가 쉬운 것이 아니다. )


  정리하자면, 번역 상태 좋으나, 번역 용어에 대해서는 약간 아쉬움이 남고, 인터프리터가 어떻게 만들어야 하는지 궁금한데, 너무 어려울 것 같다라고 생각하는 사람들에게 권하고 싶다.


ps. 원제는 "명쾌 시리즈"인데 번역하면서 "만들면서 배우는 ~" 이 된것 같다.

약간 어감이 다를 수 있지만, 단계별로 A만들고 A+ 하는 방식의 내용 전개는 아니다.

 

  

[android] Singleton.h

Framework/안드로이드 2012. 11. 17. 02:20 Posted by byulbit
안드로이드 프레임웍에 있는 싱글톤은 템플릿으로 구현이 되어 있다. 

보통 다른 곳에서는 상속기반의 CRTP로 싱글톤을 구현하지만, 이와 약간 다르게 구현이 되어 있다. 

아래 소스는 멀티스레드와 관련된 기능은 제외한 안드로이드 싱글톤 템플릿 클래스이다.
#ifndef ANDROID_UTILS_SINGLETON_H
#define ANDROID_UTILS_SINGLETON_H

namespace android {

template 
class Singleton
{
public:
	static T& getInstance() {
		T* instance = sInstance;
		if(instance == 0) {
			instance = new T();					// Call Default Constructor
			sInstance = instance;
		}
		return *instance;
	}

protected:
	~Singleton(){}
	Singleton(){}

private:
	Singleton(const Singleton&);					// Prohibit Copy Constructor
	Singleton& operator= (const Singleton&);		// Prohibit Copy Constructor
	static T* sInstance;							// Static Instance
};

#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE)			\
	template class Singleton< TYPE >;					\	// Default Template
	template<> TYPE* Singleton< TYPE >::sInstance(0);		// Specialization


// -----------------------------------------------
};	// namespace android
#endif

  ANDROID_SINGLETON_STATIC_INSTANCE  매크로를 이용해서 template 클래스(template class Singleton<TYPE>) 와 특수화 클래스(template<> TYPE* Singleton<TYPE>::sInstance(0) )를 만든다. 

여기서 특수화는 부분 특수화가 아닌 완전 특수화이다.   부분 특수화이든, 완전 특수화이든 특수화를 하려면 선언일지라도 특수화하지 않은 template 형태(흔히 primary라고 부른다)가 필요하다.   그래서 template class Singleton<TYPE>; 이 선언형태로 들어간다.

정적 객체를 얻어올시에는 매크로를 이용하여 한번 선언한 뒤에 

Test t = Singleton::getInstance(); 

위와 같이 일반 값이나 참조의 형태로 받으면 된다. 

getInstance() 의 반환값의 형태가 참조이기 때문에 만약 포인터 변수로 받을시에는 &연산자가 필요하다.

또한 Test 클래스는 기본 생성자(Default Constructor)를 가져야 한다는 제약이 걸려 있다.   만약 인수를 받는 생성자로 호출을 원한다면, 템플릿 클래스를 수정하여야 한다.

 


STL 요소 만들어보기(4)

C++ 2012. 11. 16. 04:47 Posted by byulbit

#include <iostream>

#include <xutility>

#include <algorithm>


#include "Node.hpp"

#include "ListIterator.hpp"

#include "List.hpp"


using namespace STD; // 내가 만든 STL의 요소


int main()

{

List<> s; // Single Linked List

List<int, DNode<int>> d; // Double linked List


s.push_back(10);

s.push_back(12);

d.push_back(13);

d.push_back(14);


std::for_each( s.begin(), s.end(), [](int a) { std::cout << a << std::endl; } );

std::for_each( d.begin(), d.end(), [](int a) { std::cout << a << std::endl; } );


}


'C++' 카테고리의 다른 글

STL 요소 만들어보기(3)  (0) 2012.11.16
STL 요소 만들어보기(2)  (0) 2012.11.16
STL 요소 만들어보기(1)  (0) 2012.11.16
[C++] template을 사용하여 연결리스트 구현  (0) 2012.11.16
[C++0x] Move Operator  (0) 2012.11.16

STL 요소 만들어보기(3)

C++ 2012. 11. 16. 04:46 Posted by byulbit

#include <xutility> // bidirectional_iterator_tag


namespace STD {


template<class C >

class ListIterator

{

public:

typedef typename C::elem_type elem_type; // 요소 타입

typedef typename C::node_type node_type;

typedef typename C::node_pointer_type node_pointer_type;

typedef typename C::iterator iterator;


typedef typename C::value_type value_type;

typedef std::bidirectional_iterator_tag iterator_category;


typedef typename C::difference_type difference_type;

typedef typename C::pointer pointer;

typedef typename C::reference reference;


ListIterator(node_type* node) {

_ptr = node;

}


bool operator!=(iterator& rhs) {

return (this->_ptr) != rhs._ptr;

}


bool operator==(iterator& rhs) {

return (this->_ptr) == rhs._ptr;

}


elem_type operator*() {

return (_ptr->_data);

}



node_type* operator++() {

return _ptr = _ptr->next;

}


node_type* operator++(int c) {

return _ptr = _ptr->next;

}

private:

node_type* _ptr;

};


}

'C++' 카테고리의 다른 글

STL 요소 만들어보기(4)  (0) 2012.11.16
STL 요소 만들어보기(2)  (0) 2012.11.16
STL 요소 만들어보기(1)  (0) 2012.11.16
[C++] template을 사용하여 연결리스트 구현  (0) 2012.11.16
[C++0x] Move Operator  (0) 2012.11.16

STL 요소 만들어보기(2)

C++ 2012. 11. 16. 04:45 Posted by byulbit

namespace STD {

template<class C> class ListIterator; // LIstIterator에 대한 전방 선언

template<typename T> class Node; // Node에 대한 전방 선언

//template<typename T> class DNode; // DNode에 대한 전방 선언


template<typename T=int, class NODE=Node<T> >

class List

{

public:


typedef T elem_type;

typedef T* elem_pointer_type;


typedef NODE node_type;

typedef NODE* node_pointer_type;

typedef List<T,NODE> _THIS;

typedef ListIterator<_THIS> iterator;


// STL required

typedef T value_type;

typedef unsigned int difference_type;

typedef T* pointer;

typedef T& reference;


iterator begin() {

return ListIterator<_THIS>(_head->next);

}


iterator end() {

return ListIterator<_THIS>(_tail);

}


List() { 

_head = new NODE(0);

_tail = new NODE(0);

_tail->next = NULL;


_head->next = _tail;

_lastNode = _head;

}


void push_back(T element) {

NODE* elemNode = new NODE(element);

elemNode->next = _tail;


_lastNode->push_back( elemNode );

_lastNode = elemNode;

}


void push_back(NODE* next) {

_lastNode->push_back( next );

_lastNode = next;

}


private:

NODE* _head;

NODE* _tail;


NODE* _lastNode; // Last Node

};


}

'C++' 카테고리의 다른 글

STL 요소 만들어보기(4)  (0) 2012.11.16
STL 요소 만들어보기(3)  (0) 2012.11.16
STL 요소 만들어보기(1)  (0) 2012.11.16
[C++] template을 사용하여 연결리스트 구현  (0) 2012.11.16
[C++0x] Move Operator  (0) 2012.11.16

STL 요소 만들어보기(1)

C++ 2012. 11. 16. 04:41 Posted by byulbit

STL의 요소를 만들어보기

만드는 과정은 시간 날때마다 업데이트...

namespace STD {

	// Single Linked List
	template<typename T>
	class Node
	{
	public:
		Node(T element) {
			_data = element;
			next = NULL;
		}

		void push_back(Node<T>* right) {
			right->next = this->next;
			this->next = right;
		}

		T operator*() {
			return _data;
		}

		T* operator++() {
			this = this->next;
		}

		T _data;
		Node<T>* next;
	};

	// Double Linked List
	template<typename T>
	class DNode
	{
	public:
		DNode(T element) {
			_data = element;
			next = NULL;
			prev = NULL;
		}

		void push_back(DNode<T>* right) {
			right->next = this->next;
			this->next = right;
			right->prev = this;
		}

		T operator*() {
			return _data;
		}

		T* operator++() {
			this = this->next;
		}

		T _data;
		DNode<T>* next;
		DNode<T>* prev;
	};
}


'C++' 카테고리의 다른 글

STL 요소 만들어보기(3)  (0) 2012.11.16
STL 요소 만들어보기(2)  (0) 2012.11.16
[C++] template을 사용하여 연결리스트 구현  (0) 2012.11.16
[C++0x] Move Operator  (0) 2012.11.16
[C++0x] Move Constructor  (0) 2012.11.15

[C++] template을 사용하여 연결리스트 구현

C++ 2012. 11. 16. 01:56 Posted by byulbit

/* SingleLinkedList, DoubleLinkedList 둘 다 사용할 수 없을까? DoubleLinkedList를 만들기 위한 사전작업. */ #include <iostream> template<typename T> class Node { public: Node(T element) { _data = element; next = NULL; } void addToNext(Node<T>* right) { right->next = this->next; this->next = right; } T _data; Node* next; }; // DoubleLinekd List template<typename T> class DNode { public: DNode(T element) { _data = element; next = NULL; prev = NULL; } void addToNext(DNode<T>* right) { right->next = this->next; this->next = right; right->prev = this; } T _data; DNode<T>* next; DNode<T>* prev; }; template<typename T=int, template<typename L> class NODE=Node > class List { public: typedef T value_type; List() { _head = new NODE<T>(0); _tail = NULL; _lastNode = _head; } void addNext(T element) { NODE<T>* elemNode = new NODE<T>(element); _lastNode->addToNext( elemNode ); _lastNode = elemNode; } void addNext(NODE<T>* next) { _lastNode->addToNext( next ); _lastNode = next; } private: NODE<T>* _head; NODE<T>* _tail; NODE<T>* _lastNode; // Last Node }; int main() { List<int, Node> s; // Single Linked List List<int, DNode> d; // Double LInked LIst s.addNext(new Node<int>(10) ); s.addNext(new Node<int>(11) ); s.addNext(12); s.addNext(13); d.addNext(10); d.addNext(11); d.addNext(12); d.addNext(13); std::cout << std::endl; }


'C++' 카테고리의 다른 글

STL 요소 만들어보기(2)  (0) 2012.11.16
STL 요소 만들어보기(1)  (0) 2012.11.16
[C++0x] Move Operator  (0) 2012.11.16
[C++0x] Move Constructor  (0) 2012.11.15
[C++] C++ name decoration 혹은 name mangling  (0) 2012.11.13

[C++0x] Move Operator

C++ 2012. 11. 16. 00:20 Posted by byulbit
/*
	Move Constructor( 이동 연산자 )

	c++0x 에는 기존의 대입연산자에 이어서, 이동 연산자도 추가가 되었다.

*/

#include 

class MoveClass
{
public:
	// Default Constructor
	MoveClass() {
		std::cout << "Default Constructor Call" << std::endl;
	}
	
	// Copy Operator
	void operator=(MoveClass& a) {
		std::cout << "Copy Operator Call" << std::endl;
	}

	
	// Move Operator
	void operator=(MoveClass&& a) {
		std::cout << "Move Operator Call" << std::endl;
	}
};


// 값이 복사되는 곳에서는 일반적으로 복사 생성자가 호출된다.
MoveClass foo(MoveClass& a)
{
	MoveClass local;
	return local;		// 값이 복사 되는데, 우선순위가 존재한다.
						// MoveClass(const MoveClass& a) 형태의 복사 생성자가 존재하고,
						// MoveClass(MoveClass&& a) 형태의 이동 생성자가 존재하면
						// 이동 생성자를 호출한다.
}

int main()
{
	MoveClass a;			// Default Constructor Call
	MoveClass b;
	a = b;					// Copy operator Call
	
	a = std::move(b);		// move Operator Call

}

'C++' 카테고리의 다른 글

STL 요소 만들어보기(1)  (0) 2012.11.16
[C++] template을 사용하여 연결리스트 구현  (0) 2012.11.16
[C++0x] Move Constructor  (0) 2012.11.15
[C++] C++ name decoration 혹은 name mangling  (0) 2012.11.13
[C/C++] switch의 jump table  (0) 2012.11.07