http://sckllo7.tistory.com/entry/sizeof-%EC%97%B0%EC%82%B0%EC%9D%98-%ED%95%A8%EC%A0%95




C에서 sizeof는 해당 변수 혹은 자료형의 크기를 알아 보고자 할때 쓰이며 동적 메모리 할당인 malloc을 비롯한 여러 함수와 복합적으로 사용할 경우가 적지 않게 있습니다. 그러나 이 sizeof 를 쓸 경우에는 주의해야 할 점이 있습니다.


 일단 문제 하나를 풀어 보겠습니다.

다음 소스를 실행 시키면 어떠한 결과값이 출력 될까요?


#include<stdio.h>


int main()

{

        int a = -1;


        if (sizeof(a) > a)

                printf ("sizeof(a) > a\n");

        else

                printf ("sizeof(a) < a\n");


        return 0;



 아마 sizeof(a) > a 가 출력 될 것이라는 의견이 적지 않을 것입니다.

한번 실행을 시켜 보겠습니다.



 sizeof(a) 를 하면 a가 int형여고, int형의 크기가 4byte이기에 sizeof(a)의 값은 4이고, 그냥 a는 -1 이니, sizeof(a) > a 의 조건은 4 > -1 이 되서 참인 조건 이므로 sizeof(a) > a 가 출력되야 하는데 sizeof(a) < a가 출력이 됩니다.

 왜 이런 현상이 벌어지는 걸까요?

한번 sizeof(a)와 a의 값을 출력하는 printf 문을 넣어 컴파일해 보겠습니다.


#include<stdio.h>


int main()

{

        int a = -1;


        printf ("sizeof(a) = %d\n", sizeof(a));        // 추가된 부분

        printf ("a = %d\n", a);                                   // 추가된 부분


        if (sizeof(a) > a)

                printf ("sizeof(a) > a\n");

        else

                printf ("sizeof(a) < a\n");


        return 0;


그리고 컴파일을 하면, 다음과 같이 Warning이 뜨게 됩니다.



 위에서 7번째 줄 포맷 지정자가 %d이면 int형인데 인자의 자료형은 long unsigned int 라고 나옵니다.

즉, sizeof의 반환형은 단순한 int형가 아닌 long unsigned int형이라는 말이며, sizeof(a) > a 이 비교는 같은 자료형의 비교가 아니라는 말입니다.


 다른 예를 들어 보겠습니다.


#include<stdio.h>


int main()

{

        int a = -1;

        unsigned int b = 4;


        if (b > a)

                printf ("unsigned int b > int a\n");

        else

                printf ("unsigned int b < int a\n");


        return 0;


 이것을 실행시키면 어떤 결과값이 나올까요?



 부호없는 int형을 나타낸 unsigned int와 같은 경우에는 양수만을 표시 한다는 것은 다들 아실겁니다.

그런데 C언어는 특성상 다른 자료형을 비교하거나 연산 하게 될 경우에는 두개의 피연산자 중에 큰 자료형을 가진 피연산자 기준으로 나머지 피연산자가 거기에 맞게 임시로 형 변환이 일어나게 됩니다.

 혹여나 이해가 안되시는 분들을 위하여 아래의 소스를 컴파일 해보겠습니다.


#include<stdio.h>


int main()

{

        int a = 10;

        double b = 5.3;


        printf ("a + b = %d\n", a + b);


        return 0;


 이렇게 컴파일을 하게 될 경우,



 위와 마찬가지로 포맷 지정자가 %d이면 int형인데 인자의 자료형은 double이라고 명백히 나와 있습니다. 위에서 설명한 대로 서로 다른 자료형의 두개의 피 연산자가 연산이나 비교를 하게되면 큰 피연산자 기준으로 다른 피연산자의 자료형이 임시로 바뀌는 것을 볼 수 있습니다.

 즉, 다시 원점으로 둘아가면 int형의 크기는 4byte로써 제일 앞 비트는 부호 비트로 사용되어 -2^31 ~ 2^31 - 1 의 범위의 숫자를 표현이 가능 합니다. 그러나 unsigned int형과 같은 경우에는 제일 앞 비트를 부호 비트로 사용하지 않으므로 0 ~ 2^32 - 1 의 범위까지 표현이 가능 합니다.

 ※ 아마 sizeof 의 연산된 값이 unsigned가 붙는 이유는 자료형의 크기가 0 미만일 경우가 없기 때문 인 것 같습니다.

그러므로 실질적으로 int 보다 unsigned int 가 더 큰 값을 표현 할 수 있기에 if문 안에서 int형과 unsigned int형의 비교가 이루어 질때unsigned int 기준으로 int형이 임시로 unsigned int 형으로 변경이 되나 a의 값이 -1이기에 내부에서 값은 그래도이나 강제형 변환이 일어나 unsigned int의 최고 값인 4294967295 (2^32 - 1 ) 으로 바뀌므로 소스에서는 sizeof(a) > a 가 4 > -1 로 비교 되는 것이 아니라 4 > 4294967295 로 연산이 되기에 해당 비교문이 거짓으로 나오게 되며, 결론적으로는 sizeof(a) < a 가 출력이 되게 되는 겁니다.

'미분류' 카테고리의 다른 글

sizeof 연산의 함정  (0) 2016.01.12
windbg 명령어 모음  (0) 2016.01.12
socket 통신 개념  (0) 2015.11.01
socketaddr / sockaddr_in  (0) 2015.11.01

[출처] http://darpangs.tistory.com/entry/WinDbg-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC-1


 

WinDbg 에는 3 종류의 명령어가 있다.

  1. 일반 명령 : 일반적으로 사용하는 디버깅에 관련된 명령어 들이다. 브레이크 설정(bp), 타겟 제어(p,g) 등등
  2. 메타 명령 : 디버거에 관련된 명령이다. 명령어 앞에 . 이 붙는다. 디버깅 심벌 경로 설정 (.sympath ), 모듈 심벌 로드 (.reload ) 등등
  3. 확장 명령 : 외부 dll 로 제작된 명령이다(일종의 플러그인 ). 명령어 앞에 ! 이 붙는다. 예외상황분석( !analyze –v ) , 프로세스 구조체 보기 ( !peb ) 등등

 

구분

명령어

설명

예제

도움말 보기

.hh

도움말을 연다.

.hh .reload

// .reload 명령어에 관한 도움말을 열어본다

 

경로 설정

.sympath

디버깅 심벌 위치 디렉토리 설정

.sympath+ d:\work\bin

.srcpath

소스 파일 위치 디렉토리 설정

.srcpath+ d:\work\src

.symfix

웹 디버깅 심벌 서버 설정.

.symfix+ c:\symbols

디버깅 심벌 로딩하기

.reload

디버깅 심벌을 로드한다.

( 이 명령어는 디버깅 심벌을 준비해놓는다고 보면 될거 같다. 기본적으로 WinDbg 는 deferred symbol loading 을 수행하는데, 당장 쓰이지 않으면 디버깅 심벌을 로딩해 놓지 않는다. )

주의사항은 확장자를 붙여야 한다는것.

.reload darpangs.sys

// 디버깅 심벌 로드

 

.reload /u darpangs.sys

// 디버깅 심벌 언로드

 

.reload /i darpangs.sys

// 디버깅 심벌 강제 로드

ld

디버깅 심벌을 로드한다.

( deferred loading 된 디버깅 심벌들을 실제로 로딩한다. )

주의사항은 확장자 없이 사용한다는 것

ld darpangs

로딩된 모듈 및 디버깅 심벌 보기

lm

List Loaded Modules

현재 로딩 되어 있는 모듈들을 본다.

lmm *darpangs*

// darpangs 글자가 들어간 모듈 나열

 

lmv

// 상세 정보 표시

 

lml

// 디버깅 심벌이 로딩된 모듈만 표시.

쓰레드 보기

~

쓰레드 정보를 본다.

~*

// 모든 쓰레드를 표시한다.

 

~5

// 5번 쓰레드를 표시한다.

 

~1s

// 1번 쓰레드를 현재 쓰레드로 설정한다.

 

~#

// 예외를 일으킨 쓰레드를 본다.

스택 보기

k

현재 쓰레드의 스택을 본다.

kb

// 스택 상황을 파라미터와 함께 본다.

 

kn

// 스택 프레임 번호를 함께 본다.

 

kf

// 스택 프레임 간격을 함께 본다. 이 기능은 로컬 스택의 크기를 알 수 있다.

심벌 보기

x

특정 모듈의 심벌을 본다.

x ntdll!*create*

// ntdll 의 심벌(변수나 함수)중 create 이라는 단어가 들어간 것을 표시한다.

자료 구조 보기

dt

데이터 타잎을 본다.

디버깅 심벌이 로딩되어 있을 경우, 구조체의 정보를 보여준다.

dt ntdll!*list*

// ntdll 의 구조체 중 list 단어가 들어간 것을 모두 보여준다.

 

dt ntdll!_LIST_ENTRY

// ntdll 의 구조체 중 _LIST_ENTRY 구조체의 구성을 보여준다.

 

dt ntdll!_LIST_ENTRY 0x12345678

// 0x12345678 메모리의 데이터를 _LIST_ENTRY 구조체로 맞추어서 보여준다.

 

dt ntdll!_LIST_ENTRY 0x12345678 –r2

// 구조체 내부에 또 다른 구조체가 있을 경우, 해당 구조체의 내용도 표시해준다. 2단계까지 내용을 표시한다.

메모리 보기

d

메모리의 값을 각 형태에 맞게 본다.

 

dd

 

dd 0x12345678

// 0x12345678 메모리의 데이터를 Double Word 형태로 출력한다.

db

 

db 0x12345678

// 0x12345687 메모리의 데이터를 Byte 단위 및 ASCII 문자 형태로 출력한다.

du

 

du 0x12345678

// 유니코드 형태로 출력한다.

브레이브 포인트

bp

브레이크 포인트 설정

bp ntdll!NtCreateFile

// ntdll.dll 의 NtCreateFile 함수에 브레이크 포인트를 건다.

bu

브레이크 포인트 설정 ( 심벌 이름으로 )

bu ntdll!NtCreateFile

// ntdll.dll 의 NtCreateFile 함수에 브레이크 포인트를 건다.

아직 로딩되지 않은 모듈에 브레이크 포인트를 설정할 수 있으며, 모듈이 언로드 되거나 WinDbg 가 종료되더라도 브레이크 포인트 설정이 계속 유지된다.

bl

브레이크 포인트 리스트 보기

bl

bc

브레이크 포인트 모두 제거

bc

bd

브레이크 포인트 비활성화

bd 5

// 5번 브레이크 포인트 비활성화

be

브레이크 포인트 활성화

be 1-4

// 1번부터 4번까지의 브레이크 포인트 활성화

ba

메모리 브레이크 포인트 설정

ba w4 0x12345678

// 0x12345678 주소가 Writing 되는 시점에 브레이크가 걸린다.

 

ba r4 0x12345678

// 0x12345678 주소가 Reading 되는 시점에 브레이크가 걸린다.

브레이크

실행 제어

 

( .hh Controlling the Target )

F9 키 ( bp )

현재 src 창이나 disassembly 창의 라인에 브레이크 포인트 설정

Visual Studio 와 동일

F10 키 ( p )

src 나 disassembly 의 한라인 실행

Visual Studio 와 동일

F11 키 ( t )

함수호출 시, 함수 내부 추적.

Visual Studio 와 동일

Shift + F11 키 ( gu )

현재 함수 종료까지 실행

Visual Studio 와 동일

   
   

오류 분석

!analyze

현재 예외 상황의 원인을 분석한다.

!analyze -v



'미분류' 카테고리의 다른 글

sizeof 연산의 함정  (0) 2016.01.12
windbg 명령어 모음  (0) 2016.01.12
socket 통신 개념  (0) 2015.11.01
socketaddr / sockaddr_in  (0) 2015.11.01

 

소켓통신

프로그램과 프로그램과의 통신.
(인터넷에서 통신하느냐, 컴퓨터 내에서 통신하느냐에 등등 사용영역에 따라 다름)

소켓 생성

소켓을 생성한다는 의미는 호스트가 통신을 하기 위해 필요한 리소스를 할당하는 것을 의미.

 

함수 원형

int socket( int domain, int type, int protocol)

  • domain : 소켓의 사용영역 정의.
  • type : 소켓이 데이터를 전송하는데 있어서 사용하게 되는 전송 타입을 설정.
  • protocol : 두 호스트간에 통신을 하는데 있어서 특정 프로토콜을 지정하기 위해 사용.

 

리턴 값

성공 : file descriptor

실패 : -1

 

@domain( 프로토콜 체계)

usr/include/sys/socket.h 에 선언 되어 있는 프로토콜 체계

PF_INET : IPv4 인터넷 프로토콜
PF_INET6 : IPv6 인터넷 프로토콜
PF_LOCAL : Local 통신을 위한 UNIX 프로토콜
PF_PACKET : Low level socket을 위한 인터페이스
PF_IPX : IPX 노벨 프로토콜

- 소켓을 생성할 때 어디서 사용할 것인지 그 환경을 고려하여 프로토콜 체계를 지정해 주면 그 환경에 사용 가능한 소켓이 생성된다.
( 인터넷영역에서 사용할 것인지, 로컬 영역에서 사용할 것인지..)

 

@type ( 소켓의 타입 )

데이터의 전송 타입으로 SOCK_STREAM, SOCK_DGRAM 이 있다.

 

SOCK_STREAM : 연결 지향형 소켓
-에러나 데이터의 손실 없이 무사히 전달.
- 전송하는 순서대로 데이터가 전달.
- 전송되는 데이터의 경계가 존재하지 않음.
=> 신뢰성 있는 순차적인 바이트 기반의 연결 지향 전송 타입.

 

SOCK_DGRAM : 비연결 지향형 소켓
- 전송되는 순서에 상관없이 가장 빠른 전송을 지향.
- 전송되는 데이터는 손실될 수도 있고, 에러가 발생할 수 있음.
- 전송되는 데이터의 경계가 존재.
- 한번에 전송되는 데이터의 크기는 제한.

 

@protocol ( 프로토콜 선택 )

호스트와 호스트 사이에 사용할 프로토콜을 설정.

 

프로토콜 체계가 PF_INET인 경우 다음과 같은 값이 올 수 있다.
- IPPROTO_TCP : TCP를 기반으로 하는 소켓을 생성(연결 지향형 소켓)
- IPPROTO_UDP : UDP를 기반으로 하는 소켓을 생성(비연결 지향형 소켓)

(PF_INET)-(SOCK_STREAM) -(TCP소켓) / (PF_INET)-(SOCK_DGRAM)-(UDP소켓)

  • 1번째와 2번째 인자로 인해 프로토콜은 정해지는 것 처럼 보인다.
  • 따라서 세번째 인자 값에 0 을 입력해도 자동으로 소켓은 생성된다.

세번째 인자값의 활용

  • 하나의 프로토콜 체계 안에서 데이터 전송타입까지 같지만 최종적으로 통신하는 형태가 다른,
    즉 전송 타입은 같지만 그 안에서도 프로토콜이 또 다시 나뉘는 상황에서 이 세번째 인자가 유용한 인자가 된다.
    즉 세번째 인자는 프로토콜을 조금 더 구체화 하기위해 사용된다.

 

 

socket 함수는 위에서 다루었고, 나머지 함수에 대해 아주 간략하게 정리하겠습니다.
bind 함수는 소켓에 IP와 port를 지정해줘서 소켓을 통신에 사용할 수 있도록 준비해줍니다.
listen함수는 client로부터 연결 요청을 대기열에 넣어주는 함수입니다.
accept함수는 대기열에 있는 접속 요청을 받아들이고, client와 통신하는 전용 소켓을 생성합니다.
connect 함수는 서버로 접속을 요청하는 함수입니다.


[참조] 나머지함수 설명은 아래주소에서 참조하세요

http://forum.falinux.com/zbxe/index.php?document_srl=430926&mid=C_LIB


'미분류' 카테고리의 다른 글

sizeof 연산의 함정  (0) 2016.01.12
windbg 명령어 모음  (0) 2016.01.12
socket 통신 개념  (0) 2015.11.01
socketaddr / sockaddr_in  (0) 2015.11.01

 

sockaddr 구조체

소켓 주소를 표현하는 구조체.
TCP/IP만 목적으로 만들어진 것이 아니기 때문에, 다양한 주소체계에 맞게 구조체를 가지고 있다.

 

struct sockaddr
{

sa_family_t sa_family; /* 소켓의 주소체계 */

char sa_data[4]; /* 해당 주소체계에서 사용하는 주소정보 */

}

 

sockaddr_in 구조체

:IPv4 주소체계에서 사용하는 구조체.
소켓 프로그램은 범용 주소 구조체로 sockaddr을 사용하지만, 주소체계의 종류에 따라 별도의 전용 구조체를 만들어 사용하는게 편리하다.

* 소켓 라이브러리는 sockaddr을 사용하므로 라이브러리에 주소 정보를 넘길 때는 sockaddr로 형변환을 하여 넘긴다. 그렇기 때문에 구조체의 크기는 동일.

struct sockaddr_in

{

sin_family_t sin_family /* IPv4주소체계에서 사용하므로 항상 AF_INET */
unist16_t sin_port ; /* 포트 번호 */
struct in_addr sin_addr; /* IP주소를 나타내는 32비트 정수 타입 구조체 */

char sin_zero[8]; /* sockaddr과 같은 크기를 유지 하기 위해 필요한 패딩공간 항상 0 */

}

struct in_addr{

unit32_t s_addr; /* 32비트 IPv4 인터넷 주소 */

}

 

PF_INET주소 체계(Protocol Family)

소켓을 만들 때는 소켓이 사용될 환경을 고려해 프로토콜을 설정해 주어야 한다.
다시 말해 프로토콜 패밀리는 소켓을 생성할 때 이 소켓이 어떤 프로토콜을 사용해 통신을 할지 정해준다. 참고로 소켓은 네트워크 통신을 할 때만 사용되는 것은 아니다.
유닉스 계열의 시스템에서 시스템 내부의 프로세스들끼리 통신을 하기 위해서도 사용된다.
자주 사용되는 PF_INET는 프로토콜 패밀리중 하나다.

AF_INET 주소 체계(Address Family)

주소 구조체 안에 주소 패밀리를 정의할 때 사용.
프로토콜 체계를 나타내는 PF_INET 와 주소체계를 나타내는 AF_INET는 같은 상수 값을 갖는다. 그렇다고 해서 주소정보를 설정하는 부분에 PF_INET를 사용하고 프로토콜 패밀리 정보를 설정하는 부분에 AF_INET을 넣는 것은 좋지 않다.

 

 

 

 

 

'미분류' 카테고리의 다른 글

sizeof 연산의 함정  (0) 2016.01.12
windbg 명령어 모음  (0) 2016.01.12
socket 통신 개념  (0) 2015.11.01
socketaddr / sockaddr_in  (0) 2015.11.01

+ Recent posts