Programmer
-
C언어에서 struct 정의 그대로 이진 데이터로 만들기Programmer/Programming 2017. 1. 13. 15:15
C의 struct를 이진 데이터로 저장하고 불러오는데 원하는대로 되지 않을 때가 있다. 예를 들어, 2 바이트 이후에 적혀야 하는데 4바이트 뒤에 위치하는 경우이다. 예상한 이진 데이터의 구조: 실제 이진 데이터의 구조 (목표 머신-target machine-을 64 bits로 컴파일한 경우): 이는 데이터 구조체 정렬(data structure alignment) 때문에 발생한다. 데이타 구조체 정렬이란 해당 머신의 읽고 쓰는 단위 크기의 배수로 데이타를 할당하는 것을 말한다. 데이터가 이 배수값보다 작으면 데이터 구조체 패딩(data structure padding)을 해준다. 현대의 컴퓨터는 성능을 높이기 위해서 이런 방식을 기본으로 사용한다. 따라서, 프로그래머가 정확한 이진 데이터를 생성하려면 ..
-
교착상태(deadlock)를 프로세스 상태와 디버거를 사용해서 찾아내기Programmer/Programming 2017. 1. 6. 15:37
멀티미디어(multimedia) 소스를 수신 받아서 가공하고 송출하는 프로그램을 개선하고 있었다. 에이징 테스트(aging test)에서 얼마간 프로그램이 동작하다가 미디어를 송출하지 못하는 버그를 발견했다. 로그를 살펴보니 송출이 멈추기 전에 수신부터 진행이 되지 않는 것을 발견했다. UDP로 입력 데이터는 들어오는데 읽지 못하고 있었다. 기능이 멈춰있으면 있으면 두가지를 의심할 수 있다. 하나는 무한루프, 나머지 하나는 교착상태(deadlock)이다. 무한루프에 빠지거나 교착 상태에 진입하면 다음 단계로 나아가지 못한다. 무한 루프인지 교착 상태인지 간단하게 판단하는 방법은 프로세스의 CPU 점유율과 상태를 확인하는 것이다. `ps -u`나 top 유틸리티로 확인한다. 무한 루프는 CPU를 과도하게 ..
-
버젼 관리 시스템을 사용하여 문제를 해결하기Programmer/Programming 2017. 1. 6. 15:01
초반에는 문제의 원인을 충분히 넓게 잡아라."에서 중요한 디버깅 기법 하나를 간단하게 언급하고 넘어갔다. 분석의 과정이 없이 추론에 근거하여 새로 추가된 원격 기능과 캐싱 알고리즘만을 의심했다. 코드를 수정해도 상태가 개선되지 않았다. ... 중략 ... 이전 버젼과 차이점을 면밀하게 비교하면서 비로서 문제의 원인을 발견했다. 같은 환경과 같은 기능(즉, 로컬 파일 읽기)에서도 새 버젼에서 동일한 문제가 일어났다. 즉, 새로운 기능이 동작할 때 발생하는 것이 아니란 의미이다. 로깅 시스템을 리펙토링을 했는데, 이와 연관이 깊을 것으로 추정했고 다양한 테스트로 이를 검증했다. - 2014/07/15 - [Practice/Debugging] - 초반에는 문제의 원인을 충분히 넓게 잡아라. 버젼 콘트롤 시스템..
-
쉘스크립트에서 안전하게 문자열(string)을 비교하는 방법Programmer/Computer Skills 2016. 9. 30. 16:50
두 문자열을 안전하게 비교할 때는 if [ x$A == x$B ]; then echo $1 fi 또는 if [ "$A" == "$B" ]; then echo $1 fi 를 사용한다. 빈 문자열인지 안전하게 검사하는 방법은 if [ x$A == x ]; then echo $1 fi 또는 if [ "$A" == "" ]; then echo $1 fi 내지는 if [ -z "$A" ]; then echo $1 fi 이 있다. x와 같은 문자를 추가하거나 인용문자(")로 둘러싸지 않으면 빈문자열이거나 옵션 형태의 문자열이 들어오면 오류가 발생할 수 있다. 아래와 같이 STRING을 따옴표로 둘러싸지 않으면 [ -z STRING ] STRING이 "-n", "-p" 등을 포함한 옵션 형태의 문자열이 들어오면 문제..
-
Common Lisp으로 구현한 트리(Tree)를 중위 순회(In-order Traversal)하는 반복자(Iterator)Programmer/Programming 2016. 5. 17. 15:02
사소해 보이는 연산 뒤에 숨어있는 것 은 인턴 전화 면접에서 깨달은 내용을 담고 있다. 이 글은 인턴 면접을 소재로 하는데, 면접의 내용 중에 트리(Tree)를 중위 순회(Inorder Traversal)하는 반복자를 구현하는 것이 있다. 이 글의 필자는 C++로 구현하였다. 평소 업무에서 Common Lisp을 쓸 기회가 없어서 자꾸 잊어버린다. 도구를 갈고 닦지 않으면 녹슬기 마련이다. 간단하게 트리의 중위 순회를 Common Lisp으로 작성해봤다. 순회 순서 왼쪽의 하위 트리를 순회한다. 자신(중간) 오른쪽의 하위 트리를 순회한다. 순회할 첫번째 노드 구하기 : begin 최상위 노드의 가장 왼쪽에 있는 노드가 첫번째 노드이다. 구현은 왼쪽 하위 노드를 재귀적으로 찾는다. (defun begin ..
-
Lisp에서 클로저(closures)Programmer/Programming 2016. 2. 18. 15:57
클로저란 함수가 lexical 환경(environment)의 변수를 참조하는 것을 말한다. 예를 들면, 아래 코드를 살펴보자. (defparameter *plus-10* (let ((x 10)) (lambda (y) (+ x y)))) X와 Y를 더하는 함수 객체를 만들고, *PLUS-10*이 이를 가르키게 한다. Lexical 변수 X는 LET 구문 블럭이 생성한 환경에 갇혀서 외부에서는 접근할 수 없다. LET 구문 블럭이 종료되었다는 것은 실행 흐름이 LET이 생성한 환경에서 벗어났다는 것을 의미한다. 그럼에도 불구하고, *PLUS-10*를 호출하면 X 변수를 참조할 수 있다. CL-USER> (funcall *plus-10* 20) 30 함수 객체가 다른 곳(예제에서는 dynamic 환경의 *PL..
-
Lisp에서 lexical과 dynamic 변수 타입Programmer/Programming 2016. 2. 18. 15:43
Lisp에는 lexical과 dynamic이라는 두가지 변수(variables) 형태가 존재한다. lexical 변수는 소스 코드를 읽는 단계에서 바인딩(binding)이 결정된다. C나 Java 같은 언어에서 말하는 지역(local) 변수를 생각하면 된다. 함수의 매개변수(parameters)나 LET 구문의 변수가 이런 타입니다. 함수의 매개변수 (defun foo (x y) (+ x y)) 함수를 호출하면, 이 함수에 전달하는 인자(arguments)와 연결(binding)하는 매개변수를 생성한다. 이 변수는 함수 내로 범위가 한정된다. LET 구문의 변수 (let ((x 10) (y 20)) (+ x y)) LET 구문 역시 함수 호출과 동일한 효과를 가진다. LAMBDA로 표현하면 함수의 매개변..
-
Lisp 비교 : 암호 문자열 감추기 문제 풀이Programmer/Programming 2016. 1. 13. 18:53
"케빈 TV 12회 (상) - 느 언어엔 이런거 없지?"에 주어진 글자수만큼 '*'를 가진 문자열을 생성하는 문제가 나왔다. 여러 언어별 구현이 나왔지만, Common Lisp와 Emacs Lisp, Scheme, Clojure가 없어서 여기에 적어본다. Common Lisp: (defun hide-password (passwd) (coerce (mapcar #'(lambda (x) #\*) (coerce passwd 'list)) 'string)) Emacs Lisp: (defun hide-password (passwd) (coerce (mapcar (lambda (x) ?\*) (coerce passwd 'list)) 'string)) Scheme: (define (hide-password passw..