gdb 명령어 요약집

Computer/C/C++ 2007. 9. 20. 19:46
- 출처: http://hongten.egloos.com/416241

1. 우선 컴파일 시에 디버깅 정보를 담아야 한다.
gcc -g -o [프로그램명] [소스파일명]
디버깅 옵션인 -g 으로 컴파일하며, 최적화 옵션인 -O 은 주지 않도록 한다.

2. 실행방법
gdb [프로그램명]
gdb [프로그램명] [core파일명]
gdb [프로그램명] [실행중인프로세스pid]

3. 종료방법
q
Ctrl + d

4. 소스 찾아가기 (list)
l : main 함수를 기점으로 소스의 내용이 출력된다
l 10 : 10 행 주변의 소스가 출력되는데 10 - 5 행부터 10 + 5행까지 총 10행이 출려된다.
l func : func 함수의 소스를 출력
l -5 : 기본값으로 10줄이 출력된다고 가정하고, 다음에 출력될 라인이 11라인이라면, 10(마지막라인) - 5 라인을 중심으로 출력된다. 즉, 그대로 1~10라인이 출력된다.
l a.c:func : a.c 파일의 func 함수부분을 출력
l a.c:10 : a.c 파일의 10행을 기준으로 출력

5. 옵션
set listsize 20 : 한번에 출력하는 행의 갯수를 20개로 늘린다.
Enter : 마지막으로 수행한 명령어를 다시 수행한다

6. 프로그램 실행, 종료 (run, kill)
r : 프로그램 수행 (재시작)
r arg1 arg2 : arg1과 arg2를 인자로 프로그램 수행
k : 프로그램 수행종료

7. 역추적하기 (backtrace)
bt : 오류가 발생한 함수를 역으로 찾아간다.

8. 중단점 사용하기 (breakpoint, temporary breakpoint)
b func : func 함수에 브레이크 포인트 설정
b 10 : 10행에 브레이크 포인트 설정
b a.c:func : a.c파일의 func함수에 브레이크 포인트 설정
b a.c:10 : a.c파일의 10행에 브레이크 포인트 설정
b +2 : 현재 행에서 2개 행 이후 지점에 브레이크 포인트 설정
b -2 : 현재 행에서 2개 행 이전 지점에 브레이크 포인트 설정
b *0x8049000 : 0x8049000 주소에 브레이크 포인트 설정 (어셈블리로 디버깅 시 사용)
b 10 if var == 0 : 10행에 브레이크 포인트를 설정해되, var 변수 값이 0일 때 작동
tb : 임시 중단점을 사용하는 것으로 한번만 설정되며, 그 이후에는 삭제된다.

9. 중단점 설정하기 (condition)
condition 2 var == 0 : 고유번호가 2번인 브레이크포인트에 var변수가 0일 때 동작하라고 설정

10. 중단점 삭제하기 (clear, delete)
cl func : func 함수의 시작 부분에 브레이크 포인트 지움
cl 10 : 10행의 브레이크 포인트 지움
delete 1 : 고유번호 1번의 브레이크 포인트를 지운
cl a.c:func : a.c 파일의 func함수의 브레이크 포인트 지움
cl a.c:10 : a.c 파일의 10행의 브레이크 포인트 지움
cl : 모든 브레이크 포인트 지움

11. 중단점 정보보기 (information)
info b : 현재 설정된 브레이크 포인트의 정보를 보여준다
방향키Up/Down : 방향키 Up/Down을 누르면 히스토리 기능을 제공한다
info br + TAB : info br 로 시작하는 키워드가 히스토리에 있다면 뿌려준다
info TAB + TAB : info 뒤에 올 수 있는 인자 리스트를 보여준다
TAB + TAB : 현재 사용가능한 모든 명령어 리스트를 보여준다

12. 중단점 비활성화, 활성화 하기 (enable, disable)
disable 2 : 고유번호 2번인 브레이크 포인트 비활성화
enable 2 : 고유번호 2번인 브레이크 포인트 활성화

13. 디버깅 하기 (step, next, continue, until, finish, return, step instruction, next instruction)
s : 현재 출력된 행을 수행하고 멈추지만, 함수의 경우 함수의 내부로 들어가서 수행된다
s 5 : s를 5번 입력한 것과 동일
n : 현재 행을 수행하고 멈추지만, 함수의 경우 함수를 수행하고 넘어간다
n 5 : n을 5번 입력한 것과 동일
c : 다음 브레이크 포인트를 만날때 까지 계속 수행한다
u : for 문에서 빠져나와서 다음 브레이크 포인트까지 수행한다.
finish : 현재 함수를 수행하고 빠져나감
return : 현재 함수를 수행하지 않고 빠져나감
return 123 : 현재 함수를 수행하지 않고 빠져나감, 단, 리턴값은 123
si : 현재의 인스트럭션을 수행, 함수 호출 시 내부로 들어간다.
ni : 현재의 인스트럭션을 수행, 함수 호출 시 내부로 들어가지 않는다.

14. 감시점 설정 (watch)
watch i : i변수에 와치포인트를 설정하고 i변수가 바뀔 때마다 브레이크가 걸리면서 이전값과 현재값을 출력한다.

15. 변수 정보보기 (info, print)
info locals : 현재 상태에서 어떤 지역변수들이 있으며, 값은 어떠한지를 알 수 있다.
info variables : 현재 상태에서의 전역변수 리스트를 확인할 수 있다.
p lval : lval 값을 확인한다.
p func : func 함수의 주소값을 확인한다.
p pt : pt가 구조체라면 구조체의 주소를 확인한다
p *pt : pt가 구조체라면 구조체의 값을 확인한다.
p **pt : *pt가 구조체라면 구조체의 값을 확인한다.
info registers : 레지스트 값 전체를 한번에 확인한다.

16. 레지스트 값 및 포인터가 가리키는 구조체의 배열을 출력 (info, print)
info all-registers : MMX 레지스트를포함하여 거의 대부분의 레지스트 값을 확인한다.
p $eax : eax 레지스트의 값을 확인한다. ( ex_ eax, ebx, ecx, edx, eip )
p *pt@4 : 4크기의 배열로 gdb가 알 수 있으므로 4개의 크기만큼 가져와서 확인할 수 있다.

17. 중복된 변수명이 있는 경우 특정 변수를 지정해서 출력 (print)
p 'main.c'::var : main.c 파일에 있는 전역변수인 var 변수의 값을 출력
p hello::var : hello 함수에 포함된 static 변수인 var 변수의 값을 출력

18. 출력 형식의 지정
p/t var : var 변수를 2진수로 출력
p/o var : var 변수를 8진수로 출력
p/d var : var 변수를 부호가 있는 10진수로 출력 (int)
p/u var : var 변수를 부호가 없는 10진수로 출력 (unsigned int)
p/x var : var 변수를 16진수로 출력
p/c var : var 변수를 최초 1바이트 값을 문자형으로 출력
p/f var : var 변수를 부동 소수점 값 형식으로 출력
p/a addr : addr주소와 가장 가까운 심볼의 오프셋을 출력 ( ex_ main + 15 )

19. 타입이 틀릴 경우 타입을 변환하여 출력
p (char*)vstr : 실제 컴파일 시에 (void *)형으로 되어있었다고 하더라도 (char *)로 캐스팅 하여 보여줌

20. 특정한 위치 지정
p lstr + 4 : 예를 들어 lstr = "I like you." 라는 문자열은 "ke you."가 출력된다.

21. 변수 값 설정
p lval = 1000 : 변수값 확인 이외에는 설정도 가능하다.

22. 출력명령 요약 (print)
p [변수명] : 변수 값을 출력
p [함수명] : 함수의 주소를 출력
p/[출력형식] [변수명] : 변수 값을 출력 형식으로 출력
p '[파일명]'::[변수명] : 파일명에 있는 전역변수 값을 출력
p [함수명]::[변수명] : 함수에 있는 변수 값을 출력
p [변수명]@[배열크기] : 변수의 내용을 변수 배열의 크기 형태로 출력

23. 디스플레이 명령 (display, undisplay)
display [변수명] : 변수 값을 매번 화면에 디스플레이
display/[출력형식] [변수명] : 변수 값을 출력 형식으로 디스플레이
undisplay [디스플레이번호] : 디스플레이 설정을 없앤다
disable display [디스플레이번호] : 디스플레이를 일시 중단한다.
enable display [디스플레이번호] : 디스플레이를 다시 활성화한다.

24. 스택이란
스택의 경우는 상위 1기가는 커널에서 사용하며, 그 바로 아래 공간인 상위 0xBFFFFFFF 부터 하위로 늘어나게된다.
상세한 디버깅을 위해서는 -g 옵션으로 디버깅 정보와 --save-temps 옵션을 통해 어셈블리 코드를 얻어낼 수 있다.
상위 프레임으로 갈 수록 메인 함수에 가까워 지는 것이다.

25. 스택 프레임 관련 명령 (frame, up, down, info)
frame [N] : n번 스택 프레임으로 변경
up : 상위 프레임으로 이동
up [N] : n번 상위 스택 프레임으로 이동
down : 하위 프레임으로 이동
down [N] : n번 하위 스택 프레임으로 이동
info frame : 현재 스택 프레임 정보를 출력
info args : 현재 스택 프레임의 함수가 호출될 때 인자를 출력
info locals : 현재 스택 프레임의 함수내의 지역변수를 출력
info catch : 현재 스택 프레임의 함수내의 예외 핸들러를 출력

26. 스택 트레이스 하는법
b main 또는 원하는 곳에 브레이크 포인트를 잡고
오류가 발생할 때 까지 c를 통해 진행하면, 세그먼트 폴트 등의 오류가 발생하고 디버그가 멈추는데
여기서 bt 를 통해서 전체 스택 프레임을 확인하고 어떤 함수에서 호출시에 문제가 발생하였는지 확인
단, 일반적인 라이브러리에서는 오류발생 확률이 없다고 보고, 그 함수를 호출시에 문제를 의심한다.
다시 프레임을 이동하면서, 로컬변수와 전역변수 등을 확인하면서 디버깅이 가능하다.

27. 메모리 상태 검사 (x)
x/[범위][출력 형식][범위의 단위] : 메모리의 특정 범위의 값들을 확인할 수 있다.
이렇게 메모리를 직접 읽어보는 일은 -g 옵션을 가지고 컴파일 되지 않은 실행파일을 디버깅 할때에 자주 사용된다.
즉, x/10i main 과 같이 역 어셈블하여 해당 코드를 추측하는 것이다.

28. 출력형식
x/10 main : main 함수 시작부터 40바이트를 출력한다. 출력형식은 다음과 같다.
x/10t main : main 함수 시작부터 40바이트를 2진수로 출력
x/10o main : main 함수 시작부터 40바이트를 8진수로 출력
x/10d main : main 함수 시작부터 40바이트를 부호가 있는 10진수로 출력 (int)
x/10u main : main 함수 시작부터 40바이트를 부호가 없는 10진수로 출력 (unsigned int)
x/10x main : main 함수 시작부터 40바이트를 16진수로 출력
x/10c main : main 함수 시작부터 40바이트를 최초 1바이트 값을 문자형으로 출력
x/10f main : main 함수 시작부터 40바이트를 부동 소수점 값 형식으로 출력
x/10a main : 가장 가까운 심볼의 오프셋을 출력
x/10s main : 문자열로 출력
x/10i main : 어셈블리 형식으로 출력

29. 범위의 단위 (기본 word - 4바이트)
x/10b main : byte - 1바이트 단위 - 10바이트 출력
x/10h main : halfword - 2바이트 단위 - 20바이트 출력
x/10w main : word - 4바이트 단위 - 40바이트 출력
x/10g main : giant word - 8바이트 단위 - 80바이트 출력

30. 디스어셈블링 (disas)
disas func : 어셈블리 코드를 좀 보편적으로 보기 위한 명령어
disas 0x8048300 0x8048400 : 특정 주소 범위사이의 어셈블리 코드를 보기

31. 함수호출 (call)
call func(arg1, arg2) : 특정함수 func를 arg1, arg2 파라메터를 포함하여 호출하고, 반환값은 출력

32. 점프 (jump)
jump *0x08048321 : 해당 주소로 무조건 분기하여 인스트럭션을 계속 수행한다.
jump 10 : 무조건 10행으로 분기하여 수행한다.
jump func : func 함수로 무조건 분기하여 수행한다.

33. 시그널 전송 (signal)
info signals : 보낼 수 있는 시그널의 종류를 확인할 수 있다.
signal SIGKILL : 디버깅 대상의 프로세스에게 KILL 시그널을 보낼 수 있다.

34. 메모리의 특정 영역에 값을 설정 ( set )
set {타입}[주소] = [값] : p 명령 대신에 set 을 통해서 메모리의 특정 주소에 저장하는 것이 더 일반적이다
set {int}0x8048300 = 100 : 해당 주소에 100의 값을 입력한다.

35. gdb 환경설정 (set)
info set : 변경 가능한 환경설정 정보를 출력한다.
info functions : 함수들의 리스트를 출력
info types : 선언된 타입에 대한 리스트를 출력
set prompt psyoblade: : 프롬프트를 psyoblade: 로 변경할 수 있다.
set print array on : 배열을 출력할 때 한 행에 출력하는 것이 아니라 여러 행에 출력한다.

36. 기타 info 를 통해 알 수 있는 정보들
address catch extensions handle objects set stack tracepoints
all-registers common files heap program sharedlibrary symbol types
architecture copying float leaks registers signals target variables
args dcache frame line remote-process source terminal warranty
breakpoints display functions locals scope sources threads watchpoints

--

'Computer > C/C++' 카테고리의 다른 글

stringstream  (3) 2007.08.09
#define을 통한 macro에서 #과 ##의 용법  (0) 2007.08.08
#pragma  (0) 2007.08.08
vprintf, vsprintf,... 가변 인수 함수.  (0) 2007.08.01
bitset 클래스  (0) 2007.07.02

stringstream

Computer/C/C++ 2007. 8. 9. 22:17
재미있는 녀석을 발견했다.


stringstream 이라는 녀석...

출처: http://blog.empas.com/electr/19358611

1.요약

문자열을 스트림처럼 다룰 수 있습니다.
sprintf/wsprintf의 대용으로 사용할 수도 있고, 문자열에서 토큰을 꺼내오는 데도 사용할 수 있습니다.


2.본문

C++에서 표준 입출력을 나타내는 cin/cout을 사용해 보신 적이 있으실 겁니다. stringstream도 같은 인터페이스를 가지고 있습니다.
대신에 문자열을 상대로 입출력을 한다고 생각하시면 되죠.

예제를 우선 보시겠습니다.

----- stringstream을 사용한 예제 --------------------------

1 

2 

3    #include <sstream> 

4    #include <iostream> 

5     

6    int main(int argc, char* argv[]) 

7    { 

8        int n = 3571; 

9        char* p = "blue"; 

10     

11        std::stringstream s; 

12        s << " My favorite color is " << p << "nand my favorite number is " << n; 

13     

14        std::cout << "Sentence----------------------n"; 

15        std::cout << s.str() << std::endl; 

16     

17        std::cout << "nToken-------------------------n"; 

18     

19        while(1) 

20        { 

21            char c[100]; 

22     

23            s >> c; 

24            if( s.fail() ) 

25                break; 

26     

27            std::cout << c << "n"; 

28        } 

29     

30        std::cout.flush(); 

31     

32        return 0; 

33    } 

---- 실행 결과 -------------------------------------------------

Sentence---------------------
My favorite color is blue
and my favorite number is 357

Token------------------------
My
favorite
color
is
blue
and
my
favorite
number
is
3571

-- 예제 분석 -----------------------------------------------

3    #include <sstream> 
stringstream 은 sstream 헤더 파일에 정의되어 있습니다.

( 참고로 이번 예제에서는 using namespace std;를 사용하지 않았기 때문에 필요할 때마다 std::를 붙여주어야 합니다. 계속 보시죠)

----------------------------------------------------------

8        int n = 3571; 

9        char* p = "blue"; 

10     

지역 변수를 선언하고 있습니다.
n, p는 나중에 문자열에 집어넣으려고 만든 겁니다.

중요한 stringstream s를 선언하고 있습니다.

----------------------------------------------------------

12        s << " My favorite color is " << p << "nand my favorite number is " << n; 
이번 Tip에서의 첫번째 하이라이트 입니다. MFC의 CArchive를 쓰듯이 s에 문자열 및 숫자를 차곡차곡 넣고 있습니다.

----------------------------------------------------------

15        std::cout << s.str() << std::endl; 
넣었으면 전체 문자열을 얻을 수도 있어야 겠지요.
stringstream::str() 은 string 을 반환합니다.

string은 C++ Standard Library에서 문자열을 다루기 위해 추가된 템플릿 클래스 입니다. string 객체에서 c-style의 문자열을 얻고자 하신다면.

str.c_str(); 
처럼 하시면 됩니다. 필요하실 때 쓰세요.

----------------------------------------------------------

19        while(1) 

20        { 

21            char c[100]; 

22     

23            s >> c; 

24            if( s.fail() ) 

25                break; 

26     

27            std::cout << c << "n"; 

28        } 

문자열의 마지막까지 토큰을 뽑아내려고 while 문으로 루프를 돌리고 있습니다.

이번 Tip의 두 번째 하이라이트인 23 라인에서는

s >> c;
처럼 토큰을 뽑아내고 있습니다.

나머지 코드는 실패여부를 확인하고 화면에 찍어주는 역할을 하므로 설명은 생략하겠습니다.


3.예제



4.참고

The C++ Standard Library from scratch



- 2001.08.13 Smile Seo -

'Computer > C/C++' 카테고리의 다른 글

gdb 명령어 요약집  (0) 2007.09.20
#define을 통한 macro에서 #과 ##의 용법  (0) 2007.08.08
#pragma  (0) 2007.08.08
vprintf, vsprintf,... 가변 인수 함수.  (0) 2007.08.01
bitset 클래스  (0) 2007.07.02

#define을 통한 macro에서 #과 ##의 용법

Computer/C/C++ 2007. 8. 8. 22:52

Stringizing Operator (#)

The number-sign or “stringizing” operator (#) converts macro parameters (after expansion) to string constants. It is used only with macros that take arguments. If it precedes a formal parameter in the macro definition, the actual argument passed by the macro invocation is enclosed in quotation marks and treated as a string literal. The string literal then replaces each occurrence of a combination of the stringizing operator and formal parameter within the macro definition.

White space preceding the first token of the actual argument and following the last token of the actual argument is ignored. Any white space between the tokens in the actual argument is reduced to a single white space in the resulting string literal. Thus, if a comment occurs between two tokens in the actual argument, it is reduced to a single white space. The resulting string literal is automatically concatenated with any adjacent string literals from which it is separated only by white space.

Further, if a character contained in the argument usually requires an escape sequence when used in a string literal (for example, the quotation mark (") or backslash (\) character), the necessary escape backslash is automatically inserted before the character. The following example shows a macro definition that includes the stringizing operator and a main function that invokes the macro:

#define stringer( x ) printf( #x "\n" )

void main()
{
    stringer( In quotes in the printf function call\n ); 
    stringer( "In quotes when printed to the screen"\n );   
    stringer( "This: \"  prints an escaped double quote" );
}

Such invocations would be expanded during preprocessing, producing the following code:

void main()
{
   printf( "In quotes in the printf function call\n" "\n" );
   printf( "\"In quotes when printed to the screen\"\n" "\n" );
   printf( "\"This: \\\" prints an escaped double quote\"" "\n" );
}

When the program is run, screen output for each line is as follows:

In quotes in the printf function call

"In quotes when printed to the screen"

"This: \" prints an escaped double quotation mark"



 

Token-Pasting Operator (##)

The double-number-sign or “token-pasting” operator (##), which is sometimes called the “merging” operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token and therefore cannot be the first or last token in the macro definition.

If a formal parameter in a macro definition is preceded or followed by the token-pasting operator, the formal parameter is immediately replaced by the unexpanded actual argument. Macro expansion is not performed on the argument prior to replacement.

Then, each occurrence of the token-pasting operator in token-string is removed, and the tokens preceding and following it are concatenated. The resulting token must be a valid token. If it is, the token is scanned for possible replacement if it represents a macro name. The identifier represents the name by which the concatenated tokens will be known in the program before replacement. Each token represents a token defined elsewhere, either within the program or on the compiler command line. White space preceding or following the operator is optional.

This example illustrates use of both the stringizing and token-pasting operators in specifying program output:

#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;

If a macro is called with a numeric argument like

paster( 9 );

the macro yields

printf( "token" "9" " = %d", token9 );

which becomes

printf( "token9 = %d", token9 );


Ref. : MSDN




예를 들어..다양한 이름의 handler들에 대하여 줄줄이 써야할 경우 요런 식의 코드가 가능하다.

#define BEGINHANDLER(PACKET) \
 void PACKET##Handler::executePacket(ACE_SOCK_Stream& peer, Packet* packet) { \  PACKET* thePacket = dynamic_cast<PACKET*>(packet); \
 if ( thePacket == NULL ) throw ("Not a " #PACKET " packet!");

#define ENDHANDLER }
BEGINHANDLER(MPacketQueryResult)
{
 QueryManager::theQueryManager->queryResult(thePacket->getQueryID(), thePacket->getQueryResult(), thePacket->isRowEnd(), thePacket->isEnd());
}
ENDHANDLER

'Computer > C/C++' 카테고리의 다른 글

gdb 명령어 요약집  (0) 2007.09.20
stringstream  (3) 2007.08.09
#pragma  (0) 2007.08.08
vprintf, vsprintf,... 가변 인수 함수.  (0) 2007.08.01
bitset 클래스  (0) 2007.07.02

#pragma

Computer/C/C++ 2007. 8. 8. 22:02
출처: http://simple21.egloos.com/2465470

#pragma는
- 그리스어로 action이라는 뜻
- 각각의 컴파일마다 독립적인 기능을 제공하기 위하여 이용(다른 컴파일에서는 처리 안 될 수 있음)
- VC++에서는 많은 pragma directives가 있음(alloc_text, auto_inline, bss_seg, check_stack, code_seg, comment, component, conform, const_seg, data_seg, deprecated, function, hdrstop, include_alias, init_seg, inline_depth, inline_recursion, intrinsic, managed, message, once, optimize, pack, pointers_to_members, pop_macro, push_macro, runtime_checks, section, setlocale, unmanaged, vtordisp, warning)
- 정의 안 된 pragma directives를 사용하면 단순히 경고(warning C4068: unknown pragma)만 output 창에 출력하고, 무시됨
- 많이 사용하는 것 몇 가지만 앞으로 살펴볼 것임
- 이번시간에는 once, warning

1.#pragma once
이는 중복 include하는 것을 막는 것이다.
만일 중복 include가 되면, error C2011: 'CA' : 'class' type redefinition

#ifndef _A_H_
#define _A_H_
class CA {
...
}
#endif


#pragma once
class CA {
...
}
는 동일한 것이다.

VC++에서 자동으로 class를 만들면
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
라는 코드가 삽입되어 있는데, 이는 #pragma once가 VC++버전이 1000이상인 곳에서만 의미가 있기 때문이다.(Visual C++ 5.0 => 1100, Visual C++ 6.0 => 1200, Visual C++ .NET 2003 => 1310, Visual C++ 2005 => 1400)

2.#pragma warning(disable : 4244; once : 4101; error : 4700)
소스를 컴파일하면 error와 warning이 나타나는데, warning의 경고수준을 결정하는 것임
거의 쓸 일은 없지만, 재미로 한번 살펴보기만 하자.

void main() {
    double f;
    int k1, k2;
    int n=f;
}
이를 컴파일하면 output창에 아래의 warning이 나타난다.
warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data
warning C4101: 'k1' : unreferenced local variable
warning C4101: 'k2' : unreferenced local variable
warning C4700: local variable 'f' used without having been initialized
0 error(s), 4 warning(s)

이때 disable은 해당 warning이 output창에 나오지 않도록 무시하라는 지정
once는 동일한 warning에 대해 한번만 나오라는 것
error는 해당 warning을 error로 취급하라는 것이다.

#pragma warning(disable: 4244)
#pragma warning(once: 4101)
#pragma warning(error: 4700)
void main() {
    double f;
    int k1, k2;
    int n=f;
}
을 컴파일하면
warning C4101: 'k1' : unreferenced local variable
error C4700: local variable 'f' used without having been initialized
1 error(s), 1 warning(s)
가 나오는 것을 알 수 있다.

하지만 warning을 소홀히 하는 것은 매우 좋지 않은 습관이다.
warning도 꼭꼭 해결하고 넘어가도록 하자.
void main() {
    double f=0.;
    int n=(int)f;
}

'Computer > C/C++' 카테고리의 다른 글

stringstream  (3) 2007.08.09
#define을 통한 macro에서 #과 ##의 용법  (0) 2007.08.08
vprintf, vsprintf,... 가변 인수 함수.  (0) 2007.08.01
bitset 클래스  (0) 2007.07.02
STL - MAP  (0) 2007.02.27

vprintf, vsprintf,... 가변 인수 함수.

Computer/C/C++ 2007. 8. 1. 11:27
Stream processing engine의 debugger를 손대다가 발견한 함수.
vprintf, vsprintf인데 ....아무튼 관련자료.

- 종종 공부 좀 열심히 할껄...하고 어차피 지나간 일에 대해 후회를 한다.

출처: http://blog.naver.com/endfirst?Redirect=Log&logNo=20003220224

'Computer > C/C++' 카테고리의 다른 글

#define을 통한 macro에서 #과 ##의 용법  (0) 2007.08.08
#pragma  (0) 2007.08.08
bitset 클래스  (0) 2007.07.02
STL - MAP  (0) 2007.02.27
컨테이너 초기화및 Functor 예제  (0) 2007.02.27

mysql , C 연동.

Computer/ETC 2007. 7. 25. 14:12

프로젝트 하다가...찾은 내용들.

"ld: cannot find -lX11" error가 날때.

Computer/Linux Tips 2007. 7. 9. 17:01

Ref.: http://kldp.org/node/43963

X가 /usr/X11R6에 설치되어 있다면..

$ gcc -I/usr/X11R6/include -L/usr/X11R6/lib asdf.c -lX11

매번 -I, -L을 쓰는게 귀찮다면...

$ export LIBRARY_PATH=/usr/X11R6/lib:$LIBRARY_PATH
$ export C_INCLUDE_PATH=/usr/X11R6/include:$C_INCLUDE_PATH
$ gcc asdf.c -lX11

bitset 클래스

Computer/C/C++ 2007. 7. 2. 14:26

뭔가 bitmap을 만들어서 사용할 일이 발생했다.

shift와 modulo 연산을 열라게 하게 될 줄 알고 내심 고민..어떻게 효율적으로 짤 수 있을까 잠시 더 고민...

하다가 STL에 놀라운 녀석이 있다는 사실을 발견하였다.

------------------------------

비트 단위의 조작을 할때 사용할 수 있는 클래스.

가령, 10 비트 공간안에 10개의 값을 저장할 때 사용.

그러나, bitset 클래스가 메모리를 비트 단위로 사용하는 것은 아니고 외부로 표현 될 때 10개의 비트처럼 보인다는 거라넹~~~~


#include <iostream>
#include <bitset>


using namespace std;


int main()
{
    bitset < 5 > flags;


    flags.set ( 0 );
    flags.set ( 1 );
    flags.set ( 2 );


    cout << "상태 : " << flags << endl;

    cout << "any  : " << flags.any( ) << endl;

    cout << "test : " << flags.test(3) << endl;


    flags.reset( 1 );
    cout << "상태 : " << flags << endl;
    cout << "개수 : " << (int)flags.count() << endl;

    return 0;
}


[결과]

상태 : 00111

any  : 1

test  : 0

상태 : 00101

개수 : 2



멤버 함수로는

bitset::any()  - 어떤거라도 켜져 있으면 true 를 return.

bitset::test()  - 몇 번째 비트의 값이 켜져 있는지 꺼져 있는 지 return.

bitset::set()   - 몇 번째 비트의 값을 설정하는 함수.  ( default : 1 )

                      모든 비트를 1로 설정하는 매개 변수 없는 버전 과 특정 비트만 설정하는 매개변수

                      있는 버전이 있다. 매개 변수 있는 버전에서는 두번째가 지정할 값인데 default로

                      1 이기 때문에 인덱스만 지정해서 호출하면 1로 설정이 된다.

                 단, 일반적으로 set()은 설정, reset()은 해제라고 생각하기 때문에 만약 설정값을

                      0 (false) 으로 두면 착각할 수 있다라고 저자는 얘기하고 나 또한 그럴것 같다.

bitset::reset() - 비트를 0으로 설정하는 멤버 함수.

bitset::count() - 켜진 비트 개수를 return. size_t type로 return.


- <프로젝트와 함께 하는 STL의 아름다움> 491page 참조



출처 : http://blog.naver.com/rudalson/100011108867

'Computer > C/C++' 카테고리의 다른 글

#pragma  (0) 2007.08.08
vprintf, vsprintf,... 가변 인수 함수.  (0) 2007.08.01
STL - MAP  (0) 2007.02.27
컨테이너 초기화및 Functor 예제  (0) 2007.02.27
STL lower_bound function 사용하기 Sample...  (0) 2007.02.27

gcc로 윈도우즈 API 프로그램 만들기

Computer/Linux Tips 2007. 3. 15. 13:27

Ref. : http://blog.naver.com/namong98?Redirect=Log&logNo=15611346

이 문서에 첨부한 TextOut.cpp라는 윈도우즈 API 소스 프로그램을 TextOut.exe라는 실행 파일로 빌드하기 위해서는 아래와 같이 명령을 내려주면 됩니다. Cygwin 루트 디렉토리 아래의 bin 디렉토리가 윈도우즈 PATH에 들어가 있다면 굳이 Cygwin 안에서 다음 명령을 내릴 필요는 없습니다.


gcc -mwindows -mno-cygwin TextOut.cpp -o TextOut.exe


여기서 옵션을 간단히 설명하면,


-mwindows : 윈도우즈 API를 사용한다는 뜻입니다.


-mno-cygwin : cygwin1.dll없이도 돌아가는 프로그램을 만든다는 뜻입니다.


만들어진 TextOut.exe를 실행하면, 아래와 같은 화면이 보이고, 화면안을 클릭하면 문자열이 나타났다 사라졌다 합니다.


strip 명령을 사용하면, 실행 파일 안의 심볼을 제거해서 실행 파일의 용량을 줄일 수 있습니다. 위에서 만든 TextOut.exe 파일의 용량을 줄이려고 한다면,

strip TextOut.exe


라고 하면 됩니다. TextOut.exe 파일은 그대로 두고 다른 TextOut1.exe 라는 파일로 strip하고 싶다면,


strip TextOut.exe -o TextOut1.exe


와 같이 하면 됩니다.


제가 이 문서에 첨부한 TextOut.cpp를 컴파일 하고, strip 시켜보니 파일 크기의 변화가 아래와 같았습니다.


strip 전,
TextOut.exe : 20841

strip 후,
TextOut1.exe : 6656


윈도우즈 API 프로그램을 빌드하기 위한 옵션이 많아 입력하기 귀찮다면 윈도우즈에서는 배치 파일을 만들고 Cygwin에서는 쉘 스크립트를 만들면 편하게 작업할 수 있을 것입니다.



~끝~


좋은 하루 되세요~ ^^

'Computer > Linux Tips' 카테고리의 다른 글

VLC Compile 과 gprof Result.  (2) 2007.03.22
원격에서 X-manager로 X-window 사용하기  (0) 2007.03.19
ftp mget 사용법  (0) 2007.03.07
Linux Network Emulator  (0) 2007.03.06
Linux 방화벽 설정하기 (IPtables)  (0) 2007.02.24

STL - MAP

Computer/C/C++ 2007. 2. 27. 20:32

  STL 맵들은 기본 컨테이너들 중에서 아마 가장 복잡하고도(상대적으로 말해서) 가장 다목적인 컨테이너들일 것이다. 이 글에서는 가장 기본적인 맵인 map에 대해서만 이야기하고, 다른 트리 기반 구조체(set, multise, mulitimap) 들에 대해서는 생략하겠다. 한 종류의 맵에 대해서는 확실히 알게 되면 다른 것들도 쉽게 이해할 수 있다.


  map은 본질적으로 키-값 쌍들을 담는 컨테이너이다. map에는 임의의 두 종류의 데이터들이 키/값 상의 형태로 저장된다. 키를 통해서 값을 조회하는 데 걸리는 시간은 O(log n)인데, 해시 테이블보다는 비효율적이지만 속도의 차이는 무시할 수 있는 정도이며 삽입과 함께 정렬이 수행된다는 추가적인 장점이 존재한다. 다시 말해서는 map의 항상 정렬된 상태로 존재하는 것이다. 이는 map의 저장 방식 자체(균형 이진 트리(balanced binary, tree), 또는 적흑 트리(red-black tree)라고도 한다)가 가지고 있는 장점이다.


#pragma warning(disable:4786)
#include <map>
#include <iostream>
#include <string>
#include <algorithm>

 

using namespace std;

 

//. 맵 컨테이너들을 비교하는데 쓰이는 템플릿
template <class F, class S>
class value_equals
{
private:
   S second;
public:
   value_equals(const S& s) : second(s) {}
  

   bool operator() (pair <const F, S> elem)
   {
    return elem.second == second;
    }
};

 

//. 코드의 입력과 가독성을 돕기 위한 typedef들
typedef map<int, string> isMap;
typedef isMap::value_type isValType;
typedef isMap::iterator isMapItor;

 

void main()
{
 

isMap c;

 

 //. 키-값 쌍들을 삽입
 c.insert(isValType(100, "One Hundered"));
 c.insert(isValType(3, "Three"));
 c.insert(isValType(150, "One Hundred Fifty"));
 c.insert(isValType(99, "Ninety Nine"));

 

 //. 모든 키들과 값들을 출력
 for(isMapItor itor = c.begin(); itor != c.end(); ++itor)
   cout << "Key = " << (*itor).first << ", Value = " << (*itor).second << endl;


 //. 맵을 연관 배열처럼 다룰 수 있다.
 cout << "Key 3 Displays value " << c[3].c_str() << endl;

 

 //. 다음과 같은 방식으로 키 - 값 쌍을 삽입하는 것도 가능하다.
 isMapItor pos = c.find(123);

 if(pos != c.end())
 {

  //. 요소를 삭제하면 그것을 가리키는 반복자는 무효화 된다.
  //. 그 상태에서 그냥 pos++ 를 호출하면 정의되지 않은
  //. 행동이 발생할 것이다.

  c.erase(pos);
 }


 //. 값에 기반해서 특정한 요소를 찾고 제거한다.
 pos = find_if(c.begin(), c.end(), value_equals<int, string>("Ninety Nine"));
 

if(pos != c.end())
   c.erase(pos);

 

 //. 루프 도중에 요소를 제거하는 경우에는 이런식으로..
 for(isMapItor itr = c.begin(); itr != c.end();)
 {
   if(itr->second == "Three")
     c.erase(itr++);
   else
     ++itr;
  }

}


  value_type이라는 새로운 중간 데이터형은 컨테이너 안에 키 - 값 쌍의 형태로 저장되는 요소들은 나타내기 위한 것이다. 편의를 위해서, typedef를 이용해서 이 데이터형과 다른 데이터형들을 좀더 쓰기 쉬운 형태로 정의했다.

 

  요소(키-값 쌍)를 컨테이너에 삽입할 때에는 insert() 함수를 이용한다. 다른 컨테이너들과 유일한 차이는 map::value_type 형의 값을 넣는다는 점이다. map은 요소가 삽입될 때 자동적으로 그것을 정렬하므로 컨테이터는 항상 키에 의해 정렬된 상태를 유지한다. map을 루프로 돌려서 키들과 그에 연관된 값들을 출력하므로 이 점을 확일 할 수 있다.

 

  map은 두 개의 항목(키와 데이터)을 쌍으로 저장하는 컨테이너이므로 하나의 반복자로 두 개의 항목들에 각각 접근하는 것이 가능하려면 또다른 구조체가 존재해야 한다. 그것이 바로 value_type 구조체이다. 반복자를 역참조하면 value_type 구조체를 얻게 된다. value_type에는 first와 second라는 두 개의 데이터 멤버들이 있는데, first 키 값을 담고 있으며 second는 데이터 값을 담고 있다.

 

  map은 키 값을 통한 임의 접근도 허용한다. 이 경우 map은 연관 배열(또는 희소 배열)과 동일한 방식으로 작동하게 된다. 요소들에 접근하거나 요소들을 추가할 때에는 index() 연산사를 사용한다. 이 연산자를 사용할 때에는 주의할 점이 있다. 이 연산자로 아직 존재하지 않은 요소에 접근하려 하면 에러가 발생하는 대신 기본 생성자에 의해 새 요소가 생성되고 그것이 map에 삽입된다. 에러를 발생시키지 않고 새 요소를 추가한다는 것은 논리적인 버그의 원인 될 수 있으므로 주의하기 바란다.

 

  코드 후반부에는 find() 함수로 특정 키에 해당하는 요소를 찾는 부분이 나온다. 키들을 정렬되어 있으므로, find()의 수행 시간은 O(log n) 이다.

 

  값에 기반해서 요소를 찾는 것은 조금 더 복잡하다. 요소들은 키에 기반해서 정렬되어 있으므로 값에 기반해서 요소를 찾는데 필요한 시간은 O(n)가 된다. 이번 예제에서는 루프 구조 대신 find()_if()라는 범용적인 STL 알고리즘을 이용해서 검색을 수행한다. 이 알고리즘에는 세 개의 인자들을 통해서 검색의 시작 위치를 뜻하는 반복자와 종료 위치를 뜻하는 반복자, 그리고 알고리즘이 검색 성공 여부를 판단하는 데 사용할 함수 객체를 지정해야 한다. 두 반복자는 자명하므로 설명할 필요가 없겠지만 함수 객체(functior)에 대해서는 족므 설명이 필요할 것 같다.

 

  STL에서는 함수들 대신 중복된 함수 연산자들을 가진 클래스들이 쓰인다.(함수 연산자를 중복하는 것이 가능하다는 것을 처음 알게 된 독자도 있을 것이다) 이러한 방식은 일반적인 프로그래밍 문제에 캡슐화된, 그리고 형에 안전한 해결책의 제공을 가능하게 한다. 이번 예제에서 지정한 함수 객체는 단순 value_pair의 second 값을 비교하고 그 결과를 돌려 준다. STL에는 대부분의 문제들에서 코드에 즉시 써먹을 수 있는 함수 객체들이 준비되어 있다. 여러 알고리즘들과 그에 사용할 수 있는 함수 객체들에 대해서는 STL 관련 서적을 참고하길 바란다.

 

  find_if() 기법은 컨테이너에서 어떠한 값을 찾을 때 권장되는 방식이나, map을 직접 루프로 돌려서 요소들을 제거해야 하는 경우도 생길 수 이 있다. 코드 마지막 for 루프가 그에 대한 것이다. 그런데 STL 설계자들은 다른 컨테이너들에서와 달리 map에 대해서는 erase() 함수가 다음의 유효한 위치를 돌려주도록 구현하지 않았다.(아마 속도상의 문제 때문일 것이다.) 이 때문에 다른 컨테이너들에서와는 조금 다른 방식으로 요소들을 제거해야 한다. 요소의 제거에 따른 반복자의 무효화 피하기 위해서는 약간의 우회책이 필요하다.

 

  이번 예제에서는 for 루프문 안에서 반복자를 증가시키는 대신 루프의 본문 안에서 조건에 따라 바복자를 증가시킨다. 요소를 제거해야 하는 경우에는 후행 증가(반복자를 참조한 후 증가시킨다.)를 사용했고, 요소를 제거하지 않는 경우에는 선행 증가(먼저 증가시킨 후 참조)를 사용했다. 이런 방식을 이용하면 임시적인 반복자에 유효한 위치를 보존하는 등의 번거로움을 피할 수 있다. 그러나 선행 증가와 후행 증가의 차이에 의존하는 것은 코드를 이해하기 힘들게 만들며 디버깅이나 유지보수에도 좋지 않다. STL 설계자들이 map의 erase()를 다른 컨테이너들의 erase()와 동일한 방식으로 만들더라면(속도를 희생하더라도) 도 좋지 않았을까 싶다. 표준 위원회가 이러한 문제를 이해해서 다음 버전의 STL에서는 보다 낭느 방향으로 개선이 이루어지길 바란다.

 

  여기에서는 교과서적인 이야기를 하나 하고 넘어가야 할 것 같다. 루프 안에서는 항상 선행 증가를 사용하는 것ㅇ이 좋은 이유는 무엇일까?

 

  효율성 때문이라는 것이 정답이다. 후행증가 연산자는 변수의 이전 값을 돌려주므로 이전 값을 담을 임시적인 변수를 만들고 파괴하는 과정이 일어나게 된다. 후행 증가로도 선행증가와 동일한 방식의 루프를 만드는 것이 가능하지만, 후행 증가를 사용할 특별한 이유(위의 예제 나온 것 등)가 없다면 항상 선행 증가 또는 선행 감소 연산자를 사용하는 것이 바람직하다.

 

- 출저 : Game Programming Gems 1  중에서-

출처 : Tong - duragon님의 VC++통

'Computer > C/C++' 카테고리의 다른 글

#pragma  (0) 2007.08.08
vprintf, vsprintf,... 가변 인수 함수.  (0) 2007.08.01
bitset 클래스  (0) 2007.07.02
컨테이너 초기화및 Functor 예제  (0) 2007.02.27
STL lower_bound function 사용하기 Sample...  (0) 2007.02.27