nlkj” > file3 cat file3 grep lk file3 | cat file1 – file2...

Preview:

Citation preview

Page 1

복습● echo “file1” > file1

● echo “file2” > file2

● echo -e “asdf\nlkj” > file3

● cat file3

● grep lk file3 | cat file1 – file2

● grep lk file3 | cat /dev/fd/0 file1 file2

Integrated Development Environment (IDE)

C++ source code

MakefileProject file

object code (binary, one per compilation unit) .o

make“make” utility

Runtime/utility libraries

(binary) .lib .a .dll .so

gcc, etc.compiler

linklinker executable

program

debugger

link

An “IDE”

compile

gdb

Eclipse

Visual Studio

Make and gdb

Page 4

Index

makegdb

Page 5

make

Page 6

Contents

What is make Makefile 내용 매크로 기능 레이블 기능 매크로와 확장자 References

Page 7

What is vi

Make 유틸리티만든다 ?– 프로그램 그룹을 유지하는데 필요한 유틸리티– 명령어 방식으로 처리되는 모든 곳에서 쓰일 수 있다 .– Makefile 은 make 가 이해할 수 있도록 일종의 쉘 스크립트 언어같이 되어있다 .

필요성– 프로그램 개발에서 여러 파일과 관계있는 하나의 함수를 바꾸게 되었을 때 그 파일에 있는 함수를 이용하는 다른 파일도 새롭게 컴파일되어야 한다 .– 파일 수가 많은 경우 불편함이 생기고 실수가 생기게 된다 .

Make – GNU make utility to maintain groups of programs

Page 8

Dependency (simple case)

gcc -o program main.c bill.c fred.c

lib.hmain.c

bill.c

fred.c

program

Page 9

Dependency (simple case)

gcc -o program main.c bill.c fred.c

lib.hmain.c

bill.c

fred.c

program

Slow!!!

fred.c 만 바뀌어도 모든 소스코드를 다시 컴파일 함 .

Page 10

Dependency (in the case of a static library)

lib.hmain.c

bill.c

fred.c

main.o

bill.o

fred.o

libfoo.a

program

What have to be rebuilt when fred.cfred.c has modified?

Page 11

Makefile 의 내용 Makefile 의 내용

– makefile 은 목표 (target), 의존 관계 (dependency), 명령 (command) 의 세개로 이루어진 기본적인 규칙 (rule) 들이 계속적으로 나열되어있는 형태이다 .– 명령 부분은 꼭 TAB 글자로 시작해야 한다 . · · ·

target · · · : dependency · · ·command · · · · · ·

Page 12

Makefile 예제 간단한 Makefile

$ gcc –c main.c$ gcc –c read.c$ gcc –c write.c

$ gcc –o test main.o read.o write.o

test : main.o read.o write.ogcc –o test main.o read.o write.o

main.o : io.h main.cgcc –c main.c

read.o : io.h read.cgcc –c read.c

write.o : io.h write.cgcc –c write.c

Page 13

매크로의 사용 매크로 기능

test : main.o read.o write.ogcc –o test main.o read.o write.o

main.o : io.h main.cgcc –c main.c

read.o : io.h read.cgcc –c read.c

write.o : io.h write.cgcc –c write.c

OBJECTS = main.o read.o write.o

test : $(OBJECTS)gcc –o test $(OBJECTS)

main.o : io.h main.cgcc –c main.c

read.o : io.h read.cgcc –c read.c

write.o : io.h write.cgcc –c write.c

Page 14

레이블의 사용 레이블 기능

test : main.o read.o write.ogcc –o test main.o read.o write.o

main.o : io.h main.cgcc –c main.c

read.o : io.h read.cgcc –c read.c

write.o : io.h write.cgcc –c write.c

OBJECTS = main.o read.o write.o

test : $(OBJECTS)gcc –o test $(OBJECTS)

main.o : io.h main.cgcc –c main.c

read.o : io.h read.cgcc –c read.c

write.o : io.h write.cgcc –c write.c

clean :rm $(OBJECTS)

Page 15

매크로와 확장자 규칙 미리 정해져 있는 매크로

ASFLAGS = ← as 명령어의 옵션 세팅AS = asCFLAGS = ← gcc 의 옵션 세팅CC = cc (=gcc)CPPFLAGS = ←g++ 의 옵션CXX = g++LDLFAGS = ←ld 의 옵션 세팅LD = ldLFLAGS = ←lex 의 옵션 세팅LEX = lexYFLAGS = ←yacc 의 옵션 세팅YACC = yaccMAKE_COMMAND = make

Page 16

test : main.o read.o write.ogcc –o test main.o read.o write.o

매크로와 확장자 규칙 예제

OBJS = main.o read.o write.o

test : $(OBJS) ← 중복 제거 (.o 파일 추가시 첫줄만 수정 )gcc –o test $(OBJS)

OBJECTS = main.o read.o write.oSRCS = main.c read.c write.c

CC = gcc ← gcc 로 세팅CFLAGS = -g –c ← gcc 의 옵션에 – g 추가TARGET = test ← 결과 파일을 test 라고 지정$(TARGET) : $(OBJECTS)$(CC) –o $(TARGET) $(OBJECTS)

clean :rm –rf $(OBJECTS) $(TARGET) core

main.o : io.h main.cread.o : io.h read.cwrite.o : io.h write.c

Version 1

Version 2

Version 3

Page 17

매크로와 확장자 규칙 확장자 규칙

– 파일의 확장자를 보고 , 그에 따라 적절한 연산을 수행시키는 규칙.SUFFIXES : .c .o

OBJECTS = main.o read.o write.oSRCS = main.c read.c write.c

CC = gcc CFLAGS = -g -c INC = -I/home/raxis/include

TARGET = test

$(TARGET) : $(OBJECTS)$(CC) –o $(TARGET) $(OBJECTS)

%.o : %.c io.h$(CC) $(INC) $(CFLAGS) $<

clean :rm –rf $(OBJECTS) $(TARGET) core

← include 패스 추가

<- 사용자가 확장자 규칙을 구현 ($< 는 소스파일을 의미함 )

Version 4

Page 18

Makefile

main.c

read.c

write.c

io.h

Page 19

References

makefile Full Guide– http://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-1.html

makefile Tutorial– http://www.opussoftware.com/tutorial/TutMakefile.htm

List of Commands – http://www.smashingmagazine.com/2010/05/03/vi-editor-linux-terminal-cheat-sheet-pdf/

Page 20

gdb

Page 21

Contents

What is gdb? gdb 의 사용법

References

10/2/19

Page 22

What is gdb?

디버거의 목적 ? – 프로그램 실행동안 프로그램 내부에서 진행되고 있는 것이 무엇인지를 알도록 하는데에 있다 . ( 또는 다른 프로그램이 종료되는 순간에 무엇을 했는지 )

gdb 의 목적 ?– 프로그램을 시작할 때 프로그램의 행동에 영향을 줄 수 있는 것을 지정할 수 있다 .– 프로그램을 지정된 조건에서 멈추도록 만든다 .– 프로그램이 멈추었을 때 무엇이 일어났는지를 시험할 수 있다 .– 프로그램내의 어떤 인자를 바꾸어서 , 버그를 고칠 수 있도록 실험을 할 수 있게 하고 다른것에 대해 배우도록 한다 .

Page 23

디버그용 컴파일 하기 컴파일 하기

– 디버그 하기 전에 , 디버그 하고자 하는 프로그램에 디버깅 정보를 컴파일 한다 . Gdb 가 사용했던 변수 , 라인 및 함수를 실행할 수 있게 된다 . Gcc 에서 ‘ g’ 옵션을 이용하여 프로그램을 컴파일 한다 .$ gcc –g example.c –o example

Page 24

gdb 실행하기 gdb 실행하기

– gdb 는 쉘에서 ‘ gdb’ 명령으로 실행된다 . gdb 에서 파일 명령으로 디버깅 용 프로그램을 로드할 수 있다 . ( 예 : ‘file example’).– 프로그램과 동일한 디렉토리에서 명령이 실행되어 , 일단 로드 되면 gdb command인 ‘ run’ 으로 프로그램이 시작한다 .

Linux 사용자의 경우 cgdb 를 사용하면 더 편함 .

설치 방법 :sudo apt-get install cgdb

Page 25

디버깅 세션의 예제 예제코드

– 루프문을 통해 곱셈 결과를 출력하고 , 마지막에 assert 문을 이용하여 강제로 오류를 발생시켜 종료하는 프로그램#include <stdio.h>#include <assert.h>int test(){ int i = 0; int j = 0; for( i = 0; i < 4; ++i ) for( j = 0; j < 4; ++j ) printf( "%d x %d = %d\n", i, j, i * j ); }int main(){

int k=0;test();

assert( 0 ); exit( 0 );}

Page 26

디버깅 세션의 예제 디버깅 정보를 삽입하여 컴파일

– gdb 정보와 함께 (gdb) 콘솔 command 창으로 바뀐다 .– gdb 상에서 이 예제 프로그램을 실행한다 . 명령어는 ‘ run’ 이다 .

$ cc -g -o gdb_test gdb_test.c $ gdb gdb_test또는$ cgdb gdb_test

Page 27

디버깅 세션의 예제– assert 문 때문에 SIGABRT 시그널 메시지와 함께 프로그램이 종료됨–

– 함수 호출에 대한 스택 추적은 ‘ backtrace’ 또는 'bt' 를 통해 확인할 수 있다 .

Page 28

디버깅 세션의 예제– main ☞__assert_fail ☞ abort() ☞ raise() ☞ __kernel_vsyscall() 순으로 함수 호출을 확인

– 해당 프로그램의 소스를 보기 위해 ‘ list’ 을 입력

Page 29

디버깅 세션의 예제– 브레이크 포인트 위치 설정

– 재실행 하여 브레이크 포인트 확인

– run 을 해보면 해당 라인에서 프로그램이 gdb 로 제어권이 넘어온다 .– ‘print’ 명령을 사용하여 각 변수의 값을 확인할 수 있다 .– ‘display’ 명령은 한번 설정해두면 변수의 값을 각 단계마다 자동적으로 보여준다 .– 브레이크 포인트부터 이어서 수행하려면 ‘ cont’ 를 입력한다 .– step 과 next– step : 함수의 내부까지 추적해 들어간다 . ‘s’ 로 실행– next : 해당 함수를 한 줄로 보고 그 다음 줄로 넘어간다 . ‘n’ 로 실행– finish: 해당 함수가 끝날때까지 실행 'fin' 로 실행

Page 30

b 9 (9번째 줄에 브레이크 설정 )run

Page 31

b main (main 함수에 브레이크 설정 )run

Page 32

디버깅 세션의 예제– 브레이크 포인트 위치 확인 및 해제

– 현재 설정된 브레이크에 대한 정보는 ‘ info break’ 로 확인 .– 설정한 브레이크 지점은 ‘ disable’ 을 사용하여 해제할 수 있다 .– disable 로 브레이크를 해제하는 지점은 라인번호가 아니라 설정 순서의 번호이다 . (info 로 확인했을 때의 번호 )

Page 33

프로그램 작업 디렉토리cd directory

GDB 작업 디렉토리를 directory 로 설정한다 .

pwdGDB 작업 디렉토리를 출력한다 .

Page 34

이미 실행중인 프로세스 디버깅하기attach process-id작동중인 프로세스를 연결시킨다 . (GDB 밖에서 시작된 프로세스 )

detachGDB 제어에서 프로세스를 놓아준다 .

Page 35

자식 프로세스 죽이기kill

Page 36

브레이크 포인트 설정break function

break +offset

break –offset

break linenum

break filename:linenum

break *address

tbreak args

hbreak args

thbreak args

rbreak regex

Page 37

스택 프레임– 콜 스택은 stack frames 또는 frames 라 불리는 연속적인 조각으로 나누어진다 .– 각 프레임은 하나의 함수에 하나의 호출이 관련된 데이터이다 .– 프레임은 함수에 주어지는 인자와 함수의 지역 변수들 그리고 함수가 실행하는 주소를 포함한다 .

frame argsframe 명령어는 한 스택 프레임에서 다른 스택 프레임으로 이동하도록 하며사용자가 선택한 스택 프레임을 출력한다 .

select-frame프레임 출력 없이 한 스택 프레임에서 다른 스택 프레임으로 이동하도록 한다 .

Page 38

Page 39

backtraces

– 프로그램이 어떻게 돌아가는지에 대한 요약이다 .– 현재 실행되는 프레임에서 시작하여 호출자 ( 프레임 1) 가 뒤따라오고 그리고 스택위에 있는 많은 프레임을 위해 프레임당 한 라인씩 보여준다 .

backtracebt 전체 스택에 대한 backtrace 를 보여준다 .

backtrace nbt n

innermost n 프레임만을 출력한다backtrace –nbt –n

outermost n 프레임만 출력한다 .

Page 40

프레임 선택하기– 프로그램에서 스택이나 다른 데이터를 검사하는 대부분의 명령어들은 그 순간에 선택된 스택 프레임에서 작동한다 .

frame nf n 프레임 넘버 n 을 선택한다 .

frame addrf addr프레임 주소 addr 을 선택한다 .

up n 스택위 n 프레임으로 이동하라 .

down n스택 아래 n 으로 이동하라 .

Page 41

소스 라인 출력하기– 소스 파일에서 라인을 출력하기 위해 list 명령어를 사용한다 .– 기본적으로 10 라인이 출력된다 .– 출력하기를 원하는 파일의 일부를 지정하기 위한 여러 가지 방법이 있다 .

list linenum현재 소스 파일에서 라인넘버 linenum 을 가운데로 라인을 출력한다 .

list function함수 function 시작 근처를 가운데로 라인을 출력한다 .

list 라인들을 더 출력한다 .

list – 마지막으로 출력된 라인의 전 몇 라인을 출력한다 .

set listsize countlist 명령어는 count 소스 라인을 출력한다 .

show listsizelist 가 출력하는 라인 넘버를 출력한다 .

Page 42

소스 파일 찾기– 정규식 표현식을 위해 현재 소스 파일 탐색을 위해 두개의 명령어가 있다 .

forward-search regexpsearch regexp명령어 ‘ forward-search regexp’ 는 regexp 과의 매치를 위해 ,나열된 마지막 라인 다음으로 시작하는 각 라인을 검사한다 .

reverse-search regexp‘reverse-search regexp’ 는 regexp 과의 매치를 위해 ,나열된 마지막 라인전에 시작하고 뒤로 가는 각 라인을 검사한다 .

Page 43

소스 디렉토리 지정하기– 실행 프로그램은 가끔 컴파일된 디렉토리에서 소스 파일의 디렉토리를 기록하지 않는다 .– 컴파일될때 , 디렉토리들은 컴파일과 디버깅 세션 사이에 이동될 수 있다 .– GDB 는 소스파일을 찾기 위한 디렉토리 리스트를 가지고 있다

directory dirname …dir dirname …디렉토리 dirname 을 소스 경로의 앞에 추가한다 .

directory소스 경로를 비게한다 .

show directories소스 경로를 출력한다 .

Page 44

데이터 검사하기– 프로그램에서 데이터를 검사하기 위한 일반적인 방법은 print 명령어나 동의어인 in-

spect 이다 .print expprint /f exp

exp 는 표현식이다 .기본적으로 exp 값은 데이터 타입에 맞는 포맷으로 출력한다 .

printprint /f

exp 를 생략한다면 , GDB 는 마지막 값을 다시 출력한다 .

Page 45

표현식– print 와 많은 다른 GDB 명령어들은 표현식을 받아들이며 그 값을 계산한다 .– 사용하는 프로그래밍 언어에 의해 정의된 상수 , 변수 또는 연산자는 GDB 의 표현식에서 유효하다 .– 이것은 추가적인 표현식 , 함수 호출 , 캐스팅 그리고 문자열 상수를 포함한다 .– 전처리기 #define 명령어들에 의해 정의된 심볼들은 포함되지 않는다 .

@‘@’ 는 배열로써 메모리의 일부를 다루기 위한 이진 연산자이다 .

::‘::’ 는 이것이 정의된 파일이나 함수내 변수를 지정하도록 허용한다 .

{type} addr메모리에 있는 주소 addr 에 저장되어 있는 객체 타입 type 을 가리킨다 .

Page 46

프로그램 변수들– 사용시 가장 일반적인 표현은 대부분의 프로그램에서 변수 이름이다 .– 표현식에서 변수들은 선택된 스택 프레임에서 이해된다 .

– 프로그램이 이미 함수 foo 내에서 실행될 때는 언제나 변수 a 를 시험하고 사용할 수 있다 .– 그러나 프로그램이 b 가 선언된 블럭내에서 실행되는 동안 b 만을 사용하고 검사할 수 있다 .

global (or static)또는 프레임내 실행 시점에서 프로그램의 영역 규칙에 따라 보여진다 .이것은 함수내에서 의미가 있다 .

void foo ( int a){

bar (a);{

int b = test ();bar (b);

}}

Page 47

인공배열– 이것은 메모리내 같은 타입의 연속적인 객체들을 출력하는데 유용하다 .

int *array=(int *) malloc (len * sizeof (int));사용자는 array 의 내용을 출력할 수 있다 .

p *array@len‘@’ 의 왼쪽 피연산자는 메모리에 남아있다 .이 방법으로 ‘ @’ 하고 같이 만든 배열 값들은 다른 배열들 처럼 행동한다 .그리고 표현식에서 사용될 때 포인터를 마음대로 할 수 있다 .

인공배열을 만들기 위한 다른 방법은 형변환을 사용하는 것이다 .(gdb) print /x (short[2])0x12345678 또는(gdb) p/x (short[2])0x12345678$1 = {0x1234, 0x5678}

배열의 길이를 뺀다면 (`(type)[])value‘)GDB 는 그 값을 채우기 위해 크기를 계산한다 . (`sizeof(value)/sizeof(type)':

(gdb) p/x (short[])0x12345678$2 = {0x1234, 0x5678}

Page 48

출력 형식– 기본적으로 GDB 는 데이터 타입에 따라서 값을 출력한다 .

x 정수로써 값을 간주한다 . 그리고 16 진수로 정수를 출력한다 .d 부호화된 10 진수 정수로 출력한다 .u 부호화되지 않은 10 진수 정수로 출력한다 .o

8 진수 정수를 출력한다 .t 이진수로 정수를 출력한다 . 문자 ‘ t’ 는 ‘ two’ 를 나타낸다 .a

16 진수로 주소와 그리고 가장 가까운 전 심볼에서 오프셋을 출력한다 .c 정수로 간주하고 문자 상수로써 출력한다 .f 부동 소수점 수로 값을 간주하고 전형적인 부동 소수점 문접을 사용하여 출력한다 .

Page 49

메모리 검사하기– 프로그램의 데이터 타입에 의존하지 않고 여러 형식으로 메모리를 검사하기 위해 x 명령어를 사용할 수 있다 .

x/nfu addrx addrx 메모리를 검사하기 위해 x 명령어를 사용해라n, 반복수반복 수는 10 진 정수이다 .f, 출력 형식출력 형식은 print ‘s’(null 로 끝난 문자열 ),또는 ‘ I’( 기계어 ) 가 사용한 형식중 하나이다 .u, 단위 크기단위 크기는 다음과 같다 .

b : 바이트h : 2 바이트 (half word)w : 워드 (4 바이트 ). 기본값이다 .g : 8 바이트 (giant word)

Page 50

자동 디스플레이– 표현식 값을 자주 출력하기를 원한다면 , gdb 가 프로그램을 멈출 때 마다 해당 값을 출력하도록 하기 위해 표현식을 자동 디스플레이 리스트에 추가한다 .

display exp프로그램이 멈출 때 마다 출력하기 위해 표현식 리스트에 표현식 exp 를 추가display /fmt exp

fmt 로 출력 포맷만을 지정하고 크기와 카운트는 지정하지 않기 위해 ,표현식 exp 를 자동 디스플레이 리스트에 추가한다 .

display /fmt addrfmt ‘I’ 나 ‘ s’, 또는 단일 크기나 유닛의 수를 포함하기 위해 ,프로그램이 멈출 때 마다 검사하기 위한 메모리 주소로써 표현식 addr 을 추가

Page 51

print 설정하기– GDB 는 배열 , 구조체 그리고 심볼들을 출력하는 방법을 제어하기 위해 다음 방법을 제공한다 .

set print addressset print address on

GDB 는 스택 발자취 , 구조체 값 , 포인터 값 , breakpoints 등등의 주소를나타낼 때 조차 이들의 위치를 보여주는 메모리 주소를 출력한다 .

set print address off내용들을 출력할 때 주소를 출력하지 마라 .

show print address주소를 출력할지 안할지를 보여준다 .

set print symbol-filename on소스파일 이름과 주소의 symbol 형태에 있는 symbol 의 라인 수를 출력하게한다 .

set print symbol-filename off소스파일 이름과 symbol 의 라인 수를 출력하지 말아라 .

show print symbol-filenameGDB 가 소스파일 이름과 주소의 symbol 형태에 있는 symbol 의 라인수를 출력할지안할지를 보여준다 .

CGDB 전용 단축키(vi 처럼 edit mode, insert mode 가 있음 )

● <esc> : goto source window ↔ i : goto gdb window

● Source window shortcuts:

– <F5> :run

– <F6> :continue

– <F7> :finish

– <F8> :next

– <F10> :step

( 동작 안하면 단축키 변경이 필요함 )

예 :map <F2> :step<CR>

– gg : Move to the top of file.

– G : Move to the bottom of file.

– / : search from current cursor position.

– ? : reverse search from current cursor position.

– n (N) : next forward (reverse) search.

– o : open the file dialog.

– <space> : toggle breakpoint

Page 53

References

GDB Full Guide– http://korea.gnu.org/manual/release/gdb/gdb.html

Simple Guide– http://hermet.pe.kr/88589788

Page 54

Quiz

● 다음장의 프로그램 컴파일 (make)

● io.h 를 수정후 make 했을때 다시 만들어지는 파일은 ?

● main.c 를 수정후 make 했을때 다시 만들어지는 파일은 ?

● cgdb 를 이용하여 버그를 찾고 수정하시오 .

Page 55

Makefile

main.c

read.c

write.c

io.h

Carnegie Mellon

C-1

int main() {int* a = malloc(100*sizeof(int));for (int i=0; i<100; i++) {

if (a[i] == 0) a[i]=i;else a[i]=0;

}free(a);return 0;

}

Carnegie Mellon

C-2

int main() {char w[strlen("C programming")];strcpy(w,"C programming");printf("%s\n", w);return 0;

}

Carnegie Mellon

C-3

struct ht_node {int key;int data;

};typedef struct ht_node* node;

node makeNnode(int k, int e) {node curr = malloc(sizeof(node));node->key = k;node->data = e;return node;

}

Carnegie Mellon

C-4

char *strcdup(int n, char c) {char dup[n+1];int i;for (i = 0; i < n; i++)

dup[i] = c;dup[i] = ’\0’;char *A = dup;return A;

}

Carnegie Mellon

C-5

#define IS_GREATER(a, b) a > binline int isGreater(int a, int b) {

return a > b ? 1 : 0;}int m1 = IS_GREATER(1, 0) + 1;int m2 = isGreater(1, 0) + 1;

Carnegie Mellon

C-6

#define NEXT_BYTE(a) ((char*)(a + 1));

long a1 = 54; // &a1 = 0x100int a2 = 42; // &a2 = 0x200void* b1 = NEXT_BYTE(&a1);void* b2 = NEXT_BYTE(a2);

Carnegie Mellon

C-7

#define NEXT_BYTE(a) ((char*)(a + 1));

int a1 = 54; // &a1 = 0x100long long a2 = 42; // &a2 = 0x200void* b1 = NEXT_BYTE(&a1);void* b2 = NEXT_BYTE(&a2);

b1 is a void pointer to the address 0x104.b2 is a void pointer to the address 0x108.

Recommended