The Trip

Programing/알고리즘 2011.12.05 18:18 |


// theTrip.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
 int pepleCnt = 0;

 cin >> pepleCnt;

 float* ExpenseMoney = new float[pepleCnt];
 memset( ExpenseMoney, 0.0f, sizeof(float)* pepleCnt);

 for(int i = 0; i< pepleCnt; ++i)
  cin>> (float)*(ExpenseMoney + i);


 float sum = 0.0f;
 for(int i = 0; i< pepleCnt; ++i)
 {
  sum += ExpenseMoney[i]; //합계를 구함.
 }
 float aver = sum/ pepleCnt; //평균을 구함


 float SumOfLowThenAver = 0.0f;
 for( int i = 0; i< pepleCnt; ++i)
 {
  //평균보다 돈을 적게 낸 사람들
  if( ExpenseMoney[i] < aver )
  {
   SumOfLowThenAver += aver - ExpenseMoney[i];

  }
 }

 printf("%f\n", SumOfLowThenAver);
 cout<<"내야할 총액:"<< SumOfLowThenAver <<endl;
 

 return 0;
}

 

'Programing > 알고리즘' 카테고리의 다른 글

The Trip  (0) 2011.12.05
알고리즘 트레이닝 북 지뢰찾기  (0) 2011.12.05
알고리즘 트레이닝 북 3n+1 문제  (0) 2011.12.05
Posted by 패스맨

댓글을 달아 주세요


// Minesweeper.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include <Windows.h>
#include <iostream>

using namespace std;


//해당배열의 주위 지룃수를 리턴함
int calc(int xsize ,char* tarr, int x, int y)
{

 // 특정 배열 구역을 찾음.
 char* arr = tarr + x + (xsize * y) ;

 if( (*arr) == '*' )
  return 9;

 int MineCnt = 0;
 // 그 특정 구역역 주위를 검색.
 //예외처리


 if( *(arr - 1) == '*' )
  MineCnt++;
 if( *(arr + 1) == '*' )
  MineCnt++;

 if( *(arr + (xsize* 1)) == '*' )
  MineCnt++;
 if( *(arr - (xsize* 1)) == '*' )
  MineCnt++;

 if( *(arr -1 - ( xsize* 1)  ) == '*')
  MineCnt++;
 if( *(arr -1 + ( xsize* 1)  ) == '*')
  MineCnt++;
 if( *(arr + 1 + ( xsize* 1)  ) == '*')
  MineCnt++;
 if( *(arr + 1 - ( xsize* 1)  ) == '*')
  MineCnt++;

 

 return MineCnt;
}


int _tmain(int argc, _TCHAR* argv[])
{
 int x= 0, y =0;


 cin >> x >>y;

 cout<< "x : "<<x << " y :"<<y <<endl;

 //x축 공간 +2만큼 더잡음
 int xsize = x+2;
 

 int mallocSize = (x+2)*(y+2); // 이렇게 하는이유는
 /*
 00000 ->y축+1
 0*..0
 0**.0
 0*.*0 ->0이 2개로 x축도 +2
 00000 ->y축+1
 포인터연산으로 접근할때 참조에러 일어나지 않도록...
  */

 char* arr = new char[ mallocSize ];
 memset( arr, 0x00, mallocSize );


 cout<<"정해진 행만큼 지뢰입력"<<endl;

 //input code
 for(int i = 1; i<= y; ++i)
 {
  for(int j = 1 ; j<= x; ++j)
  {
   cin>> *(arr + j + ( xsize*i ) );
  }

 }

 cout<<endl;
 // input confirm
 for(int i = 1; i<= y; ++i)
 {
  for(int j = 1 ; j<= x; ++j)
  {

   cout<< *(arr + j + ( xsize*i ) );
  }
  cout<<endl;
 }

 cout<<endl;
 //calc
 int* arr2 = new int[ mallocSize ];
 
 for(int i = 1; i<= y; ++i)
 {
  for(int j = 1 ; j<= x; ++j)
  {
   int temp=0;
   temp = calc( xsize, arr, j,i);

   *(arr2 + j +( xsize* i) ) = (int)temp;

  }
 }


 // print code
 for(int i = 1; i<= y; ++i)
 {
  for(int j = 1 ; j<= x; ++j)
  {

   cout<< *(arr2 + j + ( xsize*i ) );
  }
  cout<<endl;
 }

 return 0;
}

 

'Programing > 알고리즘' 카테고리의 다른 글

The Trip  (0) 2011.12.05
알고리즘 트레이닝 북 지뢰찾기  (0) 2011.12.05
알고리즘 트레이닝 북 3n+1 문제  (0) 2011.12.05
Posted by 패스맨

댓글을 달아 주세요


// AlgoChallenges.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include <iostream>

using namespace std;

int Calc(int num)
{
 
 int cnt = 1;

 while( num != 1)
 {
  //짝수면
  if( (num % 2) == 0 )
  {
   num = num / 2;

  }
  else //홀수면
  {
   num =(num* 3) +1;
  }

  cnt++;

 }
 

 return cnt;

}

int _tmain(int argc, _TCHAR* argv[])
{
 int inputA =0 , inputB = 0;
 cin >> inputA >> inputB;

 int curNum= 0;
 int oldMaxNum= 0;

 cout<< "A: " << inputA << ",  B: "<< inputB <<endl;

 for(int i = inputA; i<= inputB; ++i)
 {

  curNum = Calc(i);

  if(curNum > oldMaxNum)
   oldMaxNum = curNum;

 }

 cout<< oldMaxNum <<endl;
 

 return 0;
}

 

'Programing > 알고리즘' 카테고리의 다른 글

The Trip  (0) 2011.12.05
알고리즘 트레이닝 북 지뢰찾기  (0) 2011.12.05
알고리즘 트레이닝 북 3n+1 문제  (0) 2011.12.05
Posted by 패스맨

댓글을 달아 주세요

어셈블리어

Programing/asm 2011.11.29 13:42 |

출처:http://elky.tistory.com/20

The Base knowledge of Reverse Engineering.


이번 글에서는 RE를 하는 데에 있어서의 기초 지식인 어셈블리어, 논리연산, 레지스터에 대해 간단하게 다룹니다.

1.어셈블리어
Push  : sp 레지스터를 조작하는 명령어중의 하나이다. 스택에 데이터를 저장하는데 쓰인다.
ex:) Push eax : 스택에 Eax의 값을 스택에 저장한다.
ex:) Push 20 :즉석값인 20을 스택에 저장한다.
ex:) Push 401F47 : 메모리 오프셋 401F47의 값을 스택에 저장한다.

Pop  : 이 또한 sp 레지스터를 조작하는 명령 어중 하나이다.

스택에서 데이터를 꺼내는데 쓰인다.
ex:) Pop eax :스택에 가장 상위에 있는 값을 꺼내애서 eax에 저장한다.
주의점 : Push 의 역순으로 값은 스택에서 Pop 된다.

Mov  : 메모리나 레지스터의 값을 옮길 때[로 만들 때]쓰인다.
ex:) Mov eax,ebx    :ebx 레지스터의 값을 eax로 옮긴다[로 만든다].
ex:) Mov eax,20     :즉석값인 20을 eax레지스터 에 옮긴다[로 만든다].
ex:) Mov eax,dword ptr[401F47]   :메모리 오프셋 401F47 의 값을 eax에 옮긴다[로 만든다]

Lea  : 오퍼렌드1의 값을 오퍼렌드2의 값으로 만들어준다.
ex:) Lea eax,ebx    : eax레지스터의 값을 ebx의 값으로 만든다.

Inc  : 레지스터의 값을 1증가 시킨다.
ex:) Inc eax  : Eax 레지스터의 값을 1증가 시킨다.
Dec  : 레지스터의 값을 1 감소 시킨다.
ex:) Dec eax : Eax 레지스터의 값을 1 감소 시킨다.

Add  : 레지스터나 메모리의 값을 덧셈할떄 쓰임.
ex:) Add eax,ebx   :Eax 레지스터의 값에 ebx 값을 더한다.
ex:) Add eax,50    :Eax 레지스터에 즉석값인 50을 더한다.
ex:) Add eax,dword ptr[401F47]  : Eax 레지스터에 메모리 오프셋 401F47의 값을 더한다.
Sub  : 레지스터나 메모리의 값을 뻇셈할떄 쓰임.
ex:) Sub eax,ebx   : Eax 레지스터에서 ebx 레지스터의 값을 뺸다.
ex:) Sub eax,50
Eax  : 레지스터에서 즉석값 50을 뺸다.
ex:) Sub eax,dword ptr[401F47]    :Eax 레지스터에서 메모리 오프셋 401F47의 값을 뺸다.
Nop  : 아무동작도 하지 않는다. : 90
Call : 프로시저를 호출할떄 쓰인다.
ex:) Call dword ptr[401F47]    : 메모리 오프셋 401F47을 콜 한다.
Ret : 콜 했던 지점으로 돌아간다.
Cmp : 레지스터와 레지스터혹은 레지스터 값을 비교하기 위하여 쓰인다.
ex:) Cmp eax,ebx    :Eax 레지스터와 Ebx 레지스터의 값을 비교한다.
ex:) Cmp eax,50     :Eax 레지스터와 즉석 값 50을 비교한다.
ex:) Cmp eax,dword ptr[401F47]
:Eax 레지스터와 메모리 오프셋 401F47의 값을 비교한다.
Jmp : 특정한 메모리 오프셋으로 이동할 떄 쓰인다.
ex:) Jmp dword ptr[401F47]   :메모리 오프셋 401F47 로 점프한다.
조건부 점프: Cmp나 Test 같은 명령어의 결과에 따라 점프한다.
  Je  : Cmp나 Test 의 결과가 같다면 점프
  Jne : Cmp나 Text 의 결과가 같지 않다면 점프
  Jz  : 왼쪽 인자의 값이 0 이라면 점프
Jnz  : 왼쪽 인자의 값이 0 이 아니라면 점프
Jl   : 왼쪽 인자의 값이 오른쪽 인자의 값보다 작으면 점프 (부호 있는)
Jnl  : 왼쪽 인자의 값이 오른쪽 인자의 값보다 작지 않으면(크거나 같으면) 점프 (부호 있는)
Jb   : 왼쪽 인자의 값이 오른쪽 인자의 값보다 작으면 점프(부호 없는)
Jnb  : 왼쪽 인자의 값이 오른쪽 인자의 값보다 작지 않으면(크거나 같으면) 점프 (부호 없는)
Jg   : 왼쪽 인자의 값이 오른쪽 인자의 값보다 크면 점프
Jng  : 왼쪽 인자의 값이 오른쪽 인자의 값보다 크지 않으면 (작거나 같으면) 점프
Jle   : 왼쪽 인자의 값이 오른쪽 인자의 값보다 작거나 같으면 점프 (부호 있는)
Jge  : 왼쪽 인자의 값이 오른쪽 인자의 값보다 크거나 같으면 점프
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
약 이 정도의 명령어들이 가장 많이 나오는 것들임으로
최소한 위에 나온 것 들은 외워 두도록 하자.


3. 논리연산
이 글에서는 5가지 논리연산에 대해서 쓸 것이다.
논리연산자는 두 오퍼랜드의 값의 비트들을 대응시켜 명령에 따른 적절한 값을 구하여 첫 번째 오퍼랜드의 값을 바꾸어 주는 것이다.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
AND 연산
대응되는 비트가 둘 다 1이면 결과는 1이고 그 외의 결과들은 모두 0 이 된다.
ex:) MOV EAX,8
AND EAX,10 :위를 계산하기 위해 우선 두 오퍼랜드의 값을 2진수로 바꾸어 주면 8은 1000 이 되고 10은 1010 이 되고 AND 연산은 둘 다 1이여야 1이 됨으로 결과는 1000 이 됩니다.

OR 연산
대응되는 비트 중 하나가 1 또는 둘 다 1이면 결과는 1이고 그 외는 모두 0이 된다.
ex:) MOV EAX,8
OR EAX,10
:위를 계산하기 위해 두 오퍼랜드의 값을 2진수로 바꾸어 주면 8은 1000이 되고 10은 1010이 되고 OR 연산은 한쪽 또는 양쪽 둘 다 1이면 1이고 그 외는 모두 0 임으로 결과는 1010이 된다.
XOR 연산
대응되는 비트 중에서 한 비트가 1이고 다른 비트가 0이면 1이 되고 두 개의 비트가 1이면 0 이 되고 두 개다 0 이어도 0이 된다.
ex:) MOV EAX,8
XOR EAX,10
:위를 계산하기 위해 두 오퍼랜드의 값을 2진수로 바꾸어 주면 8은 1000이 되고 10은 1010이 되고 XOR 연산은 한쪽만 1이어야 1임으로 결과는 10이 된다.

NOT 연산
NOT 연산은 오퍼랜드의 값을 반대로 하여 준다.
ex:) MOV EAX,10
NOT EAX
:위를 계산하기 위해 오퍼랜드의 값을 2진수로 바꾸어 주면 10은 1010이 되고 NOT 연산은 1 과 0을 반대로 하여 줌으로 결과는 0101 이 된다.
*Test 연산은 오퍼랜드에 영향을 주지 않으며 플래그만 세트 시키어 준다.

2.레지스터
범용 레지스터
(1) Eax 레지스터
누산기라고 불리는 Eax 레지스터는 입출력과 거의 모든 산술연산에 사용된다. 곱셈과 나눗셈, 변환 명령어 등은 반드시 Eax 레지스터를 필요하게 된다.

Eax 레지스터는 32bit의 레지스터이고 16bit 의 레지스터로 ax가 있다.
(ax는 왼쪽의 ah와 오른쪽의 al로 이루어져 있다)
 (2) Ebx 레지스터
Ebx는 베이스 레지스터라 불리며, 주소지정을 확대하기 위한 인덱스로서 사용될 수 있는 유일한 범용 레지스터 이며, 다른 일반적인 계산 용도로도 쓰인다.
Ebx는 32bit 레지스터이고 16bit로 eb가 있다.
(eb는 왼쪽의 bx와 오른쪽의 bl로 이루어져 있다)
(3) Ecx 레지스터
Ecx는 카운터 레지스터라고 불리며, 루프의 반복 횟수나 좌우방향의 시프트 비트 수를 기억한다. 그 외의 계산에도 사용된다.
Ecx는 32bit 레지스터이고 16bit로 cx가 있다.
(cx는 왼쪽의 ch와 오른쪽의 cl로 이루어져 있다.)
(4) Edx 레지스터
Edx는 데이터 레지스터라고 불리며, 몇몇 입출력 동작에서 사용 된다.
(5) Esp 레지스터
Esp는 Stack Point 레지스터로써, 스택에서 일종의 인덱스로 쓰는 레지스터다.. 스택 상의 위치를 가리킨다고 생각하시면 된다.
(6) Ebp 레지스터
Ebp레지스터는, base pointer 레지스터다.
특정 주소를 가리키고 있는 레지스터입니다. 특정 주소를 저장하고 있는 임시 주소 레지스터라고 보시면 됩니다.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

플래그 레지스터
(1) OF [Over Flow]
산술연산 후 상위 비트의 오버 플로우를 나타냄
(2) DF [Direction]
문자열 데이터를 이동하거나 비교할 때 왼쪽 또는 오른쪽으로의 방향을 결정한다.
(4) SF [Sign]
산술결과의 부호를 나타낸다.[0=양수,1=음수]
(5) ZF [zero]
산술연산 또는 비교동작의 결과를 나타낸다.
[0=결과가 0이 아님,1=결과가 0임]

(6) CF [Carry]
산술연산 후 상위 비트로부터의 캐리 그리고 시프트 또는 회전동작의 결과 마지막 비트
내용을 저장한다.

(7) TF [trap]
프로세서가 단일 스텝 모드(single-step mode)를 동작할 수 있도록 해준다.

출처:http://elky.tistory.com/20

'Programing > asm' 카테고리의 다른 글

어셈블리어  (0) 2011.11.29
OpCode of Intel Assembly 80x86  (0) 2011.03.07
Posted by 패스맨

댓글을 달아 주세요

이글은 출처글입니다
출처 : http://summerlight.tistory.com/entry/volatile과-메모리-배리어


 이전 글에서 volatile 키워드에 대해 간단하게 언급했는데, 핵심은 간단하다. volatile 속성을 가진 변수는 프로그램 밖의 다른 문맥들에 의해서도 비동기적으로 접근될 수 있다. 따라서 특정 쓰레드가 해당 변수에 하는 작업들은 다른 모든 문맥들 역시 볼 수 있어야 한다는 것이다. 하드웨어를 직접 제어하기 위해 Memory-mapped I/O를 하는 경우가 가장 대표적인 예이다.[각주:1] 고로, 프로그램 문맥 상에서는 레지스터만을 이용해서 똑같은 일을 할 수 있는 경우라 해도 가시성의 확보를 위해 컴파일러는 해당 작업을 메모리에도 저장하도록 코드를 만든다.

  

 volatile 속성을 가진 변수는 그 정의대로 동작하기 위해 컴파일러 최적화 기법 중 하나인 명령어 재배치(instruction reordering)의 대상에서 제외된다. 명령어 재배치란 빠른 연산을 위해 일부 연산의 순서를 바꾸어 파이프라인을 최대한 활용하는 최적화 기법인데, 프로그램 밖의 다른 문맥들이 접근할 때 연산의 순서가 뒤바뀐 상태라면 큰 문제가 될 수 있으므로 이러한 조치를 취하는 것이다. 명령어 재배치로 인해 프로그램이 오동작할 수 있는 유명한 예로는 double-checked locking pattern이 있다.

Singleton* getInstance()
{
    if (instance == NULL) {
        lock.lock();
        if (instance == NULL) {
            instance = new Singleton
        }
        lock.unlock();
    }
    return instance;
}

 DCLP는 프로그램 전체에서 한 번만 이루어지는 생성자 호출을 위해 객체가 생성이 된 이후에도 매 번 불필요하게 락을 얻는 오버헤드를 줄이려는 의도에서 나온 패턴이다. 이는 우선 instance가 비어 있는가부터 체크한 뒤 락을 얻어 객체가 생성되는 순간에만 락을 얻는다. 이를 제시된 코드의 흐름대로만 보면 아무런 문제가 없다. 그러나 여기에서 명령어가 재배치되기 시작하는 순간 문제가 꼬여버리게 된다. 6번째 줄을 더 잘게 쪼개어 본다면 

  1. 메모리를 할당한 뒤
  2. 생성자의 논리에 따라 할당된 메모리를 초기화하고
  3. 해당 메모리 주소를 instance에 대입한다.

 이런 순서가 될 것이다. 그런데 2번과 3번 사이에는 의존성이 없으므로 이 둘을 서로 뒤집어도 단일 프로그램 문맥 상으로는 아무런 문제가 없다. 컴파일러에 따라서는 이 둘의 순서를 뒤집는게 성능 상 더 낫다고 판단, 명령어 재배치를 하자는 결론을 내릴 수도 있다. 이렇게 되면 멀티 쓰레드 환경에서는 아래와 같은 비극이 발생할 가능성도 있다. 

  1. 쓰레드 A가 진입하여 메모리를 할당 받고 이를 instance에 대입한다.
  2. 그 뒤 생성자를 통해 메모리를 초기화하기 시작한다.
  3. 그런데 쓰레드 B가 들어와 2번째 줄을 검사한다. 이 때 instance는 NULL이 아니다.
  4. 초기화가 완료되지 않은 객체가 쓰레드 B에 의해 사용된다.

 이를 막으려면 명령어가 재배치되지 않도록 해야 한다. 이를 위해 instance에 volatile 속성을 넣으면 컴파일러에 의한 재배치는 막을 수 있을 것 같다. 그러면 이걸로 모든게 완벽하게 해결된 것일까? 안타깝게도 그런 것 같지는 않다. 명령어를 재배치하는 것은 컴파일러만이 아니라 CPU 레벨에서도 이루어지기 때문이다. 현대 CPU 중 상당수는 파이프라인 및 명령어 단위 병렬성 등을 최대한으로 활용하기 위해 명령어 간 의존성을 동적으로 분석, 수행 순서를 임의로 바꾸는 비순차 실행(Out of order execution) 기법을 적극 활용한다. 이는 컴파일과는 무관하게 런타임에 이루어지는 것으로, 단순히 생성되는 코드의 순서와 메모리 접근 여부에만 영향을 줄 수 있는 volatile 키워드로는 해결할 수 없는 문제이다.

  

 사실 따지고 보면 컴파일러에 의한 것이건 CPU에 의한 것이건 비순차적 실행이 문제가 될 수 있는 경우는 어렵지 않게 상상해 볼 수 있다. 이를테면 아래와 같은 코드를 생각해보자. 

lock.lock();
a++;
lock.unlock();

 위는 동기화 객체를 사용하는 전형적인 예이다. 그런데 만에 하나라도 비순차 실행에 의해 1번째 줄과 2번째 줄의 코드 수행 순서가 뒤바뀐다고 가정해보자.[각주:2] 우리가 이 코드를 믿고 쓸 수 있을까? 메모리 접근 순서가 제대로 보장되지 않는다면 이런 간단한 코드조차 사용할 수 없게 된다.

 크리티컬 섹션과 같은 동기화 객체에서 중요한 것은 동기화 객체에 의해 보호되는 코드 혹은 객체는 무슨 일이 있어도 동시에 한 쓰레드만이 사용할 수 있어야 한다는 것이다. 이러한 목적을 달성하려면 동기화 객체 사용 이전과 이후를 기준으로 메모리 읽기/쓰기가 구분되어야 한다. 이를 위해 프로세서 내부의 메모리 읽기/쓰기의 순서를 코드에 명시된 순서대로 하도록 제약하는 메모리 배리어(Memory barrier)라는 개념이 도입된다. 메모리 배리어의 종류에도 몇 가지가 있으나, 위와 같은 목적으로는 특정 시점을 기준으로 이전의 모든 읽기/쓰기를 완료한 뒤 이후의 읽기/쓰기를 재개하는 풀 메모리 배리어가 사용된다.

 MSDN에 나온 바에 따르면 Win32 API에서는 각종 동기화 객체와 연관된 함수, 원자적인 연산인 Interlocked 계열 함수, 쓰레드를 블럭시키는 함수에서 메모리 배리어가 사용되며, POSIX쪽의 메모리 배리어에 대해서는 알아보진 않았지만 아마 상식적으로 볼 때 비슷할 것이다. 거기에 C++0x에서는 메모리 배리어가 강제되는 원자적인 연산 관련 함수들이 추가된다. VS2005 이후의 VC++에서는 volatile 키워드에 메모리 배리어를 추가했다지만,[각주:3] 표준 구현이 아니니 volatile을 동기화 목적으로는 사용하지 않는게 좋을 것 같다.

 

 멀티 쓰레드 프로그래밍이 어려운 까닭은 다른게 아니라 이런 로우 레벨의 개념들이 제대로 추상화가 되지 않은 상황이라 이들을 모르고 사용하면 쉽게 잡아내기 어려운 버그가 속출할 수도 있다는 것이다. 게다가 이를 부정확하게 알고서 동기화에 volatile을 함부로 쓴다거나 하는 경우 퍼포먼스가 낮아지는 것은 둘째치고 잡아낼 수 없는 버그가 속출할 가능성이 무척 높다. 자기가 잘 모르는 내용은 아예 쓰지 말도록 하자. 지금 이 말 쓰면서 스스로가 찔리긴 하지만 ;

  

 - 결론 

  • volatile considered harmful - 동기화에는 명시적으로 동기화 객체나 atomic operation만 쓰자.
  • 컴파일러와 프로세서에 의한 명령어 재배치는 엄연히 다른 개념이니 구분하자.
  1. 사실 Memory-mapped I/O 때문에 volatile 키워드가 생긴 것이라고 봐도 과언이 아니다. [본문으로]
  2. 물론 제대로 된 동기화 객체라면 이럴 일은 절대 없다. [본문으로]
  3. http://msdn.microsoft.com/en-us/library/ms686355(VS.85).aspx [본문으로]
Posted by 패스맨

댓글을 달아 주세요

  1. Chicago Blackhawks Jersey 2013.07.25 00:00 신고 Address Modify/Delete Reply

    창밖을 봐 바람에 나뭇가지가 살며시 흔들리면 네가 사랑하는 사람이 널 사랑하고 있는거야.


#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


class testclass
{
public:
 testclass();
 ~testclass();

 

};

int _tmain(int argc, _TCHAR* argv[])
{

 auto func = [](int n) {cout<<"number:" << n <<endl; } ;

 func(333);

 auto func1 = [](){return 3.14; };

 float f1 = func1();

 cout<<f1<<endl;


 vector<int> moneys;
 moneys.push_back(1000);
 moneys.push_back(999);

 int totalmoney = 0;

 for_each(moneys.begin() , moneys.end(),  [&totalmoney](int money)
  {
   totalmoney += money;
  }
 );

 cout<<"totalmoney:" <<totalmoney<<endl;

 return 0;
}

Posted by 패스맨

댓글을 달아 주세요



#include "stdafx.h"
#include <iostream>
#include <functional>
#include <string>

using namespace std;

function< void() > f()
{
 std::string str("abcd");

 return [=] { cout<< "hello, " << str << endl; };

}

int _tmain(int argc, _TCHAR* argv[])
{

 auto func = f();

 func();// 출력 결과 : hello, abcd

 f()(); // 출력 결과 : hello, abcd

 f(); //출력결과없음

 return 0;

}

Posted by 패스맨

댓글을 달아 주세요


출처 : http://kukuta.tistory.com/27

 오늘은 소켓의 종료와 그에 따라 발생하는 소켓의 상태 변화에 대해 알아 보도록 하겠다.

 먼저 소켓은 생성될 때는 3-way hand shaking을 통해서 생성되지만, 종료 될때는 한단계 더 많은 4-way hand shaking을 거쳐 종료 된다.

four way handshake

four way handshake


  위에서 분명히 4-way.. 4단계라고 이야기 했다. 그럼 어떤 4단계를 거치는지 알아 보자.

  1. A가 B에게 연결 종료를 요청한다.
  2. B는 바로 종료를 하는 것이 아니라, 단순히 ACK만을 날리고 있다. B도 종료 하기 전에 할
     일이 있기 때문에 바로 FIN을 날리지 않고, 단순히 ACK를 날리고 CLOSE_WAIT 상태로 넘어
     간다.
 3. 볼일을 다 보고난 B는 이제서야 FIN을 날리고 연결을 종료 하고자 한다.
 4. A는 B의 FIN을 잘 받았다는ACK를 B에게 보내게 되고, A의 ACK를 받으면 B는 종료한다.

 4의 과정에서 A는 ACK를 날리고 난후 소켓이 제거될때 까지 TIME_WAIT상태에 있게 되며 이 시간은 대략 30 초 정도지만 시스템 마다 다르다.
 TIME_WAIT에 있는 동안에는 커널이 주소와 port를 바인딩 하고 있기때문에 재사용 할 수가 없다. 게다가 TIME_WAIT에 있는 주소와 port를 재사용 요청을 하면 TIME_WAIT 시간을 더욱 늘릴 뿐이다.
 
 그렇다면 이렇게 불편한 TIME_WAIT를 왜 사용해야만 하는가??
 만일 A가 B로 보낸 마지막 종료 메시지(SEQ:5001,ACK:6002) 이후 바로 종료 했다고 가정하자. 그런데 라우터의 문제라던지 기타등등의 네트워크 상에서 발생하는 어떠한 원인에 의해 마지막 종료 메시지가 B에 도착하지 않게되었다.
 이때쯤 되면 B는 종료하지 못하고(TCP는 소심해서 뭘 하던지 완료 메시지를 받아야 마음을 놓는다) 다시 A에게 한번 더 FIN(SEQ:6001, ACK:5001)을 날린다.
 여기서 A가 TIME_WAIT가 아니라 바로 종료 되어버린 상태 였다면, 이 마지막 FIN 역시 무시했을 테고 B는 여전히 A가 종료 되었는지 살아 있는지 모르고 아둥바둥거리고 있게 될 것이다. 하지만 TIME_WAIT에 있는 A의 소켓은 여전히 주소와 포트를 바인딩 하고 있는 상태이기 때문에 다시 날아 오는 B의 FIN을 감지하고 다시한번 마지막 ACK를 날려 줄 수 있는 것이다.

참 고 :
 열혈강의 TCP/IP 소켓 프로그래밍 : 윤성우
 Unix Network Programming : Stevens

관련 글 :  
 TIME_WAIT state vs SO_REUSEADDR option -> http://kukuta.tistory.com/17

'Programing > Network' 카테고리의 다른 글

소켓 종료와 TIME_WAIT(Socket termination and TIME_WAIT)  (1) 2011.05.17
Posted by 패스맨

댓글을 달아 주세요

  1. kukuta 2011.05.28 13:31 신고 Address Modify/Delete Reply

    참고로 http://kukuta.tistory.com/155 같이 보시면 더 도움이...
    암튼 들러 주셔서 감사합니다.

출처 http://kuaaan.tistory.com/99

Q1: 동일한 스레드에서 동일한 CriticalSection에 두번 진입하면 Block이 걸릴까?
A1: 아니다. 스레드가 이미 자신이 소유한 CriticalSection을 다시 소유하려고 시도하는 것은 전혀 문제될 것이 없다. CriticalSection 개체는 내부적으로 LockCount와 OwningThread라는 멤버가 있어서 자신이 몇번 Lock이 걸렸는지와 어느 스레드에 소유되었는지를 기억하고 있다. 
다른 스레드가 소유한 CriticalSection 개체에 대해 EnterCriticalSection을 시도하면 당연히 Block되겠지만, CriticalSection을 소유한 스레드가 다시 EnterCriticalSection을 시도하면 즉시 리턴되고, 내부적으로 LockCount가 하나 증가한다. 대신, EnterCriticalSection한 횟수만큼 LeaveCriticalSection을 호출해주어야 CriticalSection 개체가 Signaled 상태로 돌아온다. 두번 EnterCriticalSection한 후 한번만 LeaveCriticalSection하면? 당연히 한번 EnterCriticalSection했을 때의 상태와 동일해진다.

디버거에서 CriticalSection 개체를 들여다 보면 아래와 같은 멤버들로 구성된 것을 알 수 있다. LockCount의 초기값은 -1이고, 한번 소유되면 0으로 증가한다.

※ 참고로... linux의 posix mutex는 lock을 두번 걸 경우 데드락에 걸리는 문제가 있었다.


Q2: A라는 스레드가 소유한 CriticalSection을 B라는 제3의 스레드가 해제할 수 있나?
A2: 그렇다. CriticalSection에 진입할 때는 Thread를 확인하지만 Leave할때는 확인하지 않으며, 임의의 스레드라도 CriticalSection을 해제할 수 있다.

Q3: 어느 Thread에도 소유되지 않은 CriticalSection에 대해 LeaveCriticalSection을 호출하면 어떻게 되나?
A3: 이런 일이 벌어져선 안된다 ㅡ.ㅡ. LeaveCriticalSection을 호출하면 LockCount가 초기값인 -1에서 하나 더 감소하여 -2가 된다. 이 상태에서는 LeaveCriticalSection을 호출했던 스레드를 포함하여 어떠한 스레드도 EnterCriticalSection을 할 수 없게 된다. (시도하면 Block된다.)
이런 경우 CriticalSection을 삭제하고 다시 만드는 방법밖에 없다.

Q4: CriticalSection을 소유한 Thread가 죽어버리면 CriticalSection은 Lock이 풀릴까?
A4: 풀리지 않는다. (반면에 커널객체인 Mutex나 Event 등은 소유한 Process가 죽으면 소멸된다.) 따라서 이런 일이 벌어지면 Application이 Hang 걸려버리는 경우가 생긴다. 단, 위에서 언급한 바와 같이 소유한 Thread가 죽어버린 CriticalSection을 제 3의 Thread가 LeaveCriticalSection 해줄 수는 있다.

※ Mutex의 경우 해당 개체를 소유한 Thread가 죽으면 자동으로 Signaled 상태로 변경된다. 즉, 저절로 Lock이 풀리게 된다. 이때 WaitForSingleObject()로 대기중이던 스레드는 함수 리턴값으로 WAIT_ABANDONDED 을 받게 된다. (CriticalSectioin과 Mutex의 차이)

출처 : http://kuaaan.tistory.com/99
Posted by 패스맨

댓글을 달아 주세요

http://www.jegerlehner.ch/intel/opcode.html

TRANSFER
Name Comment Syntax
MOV Move (copy) MOV Dest,Source
XCHG Exchange XCHG Op1,Op2
STC Set Carry STC
CLC Clear Carry CLC
CMC Complement Carry CMC
STD Set Direction STD
CLD Clear Direction CLD
STI Set Interrupt STI
CLI Clear Interrupt CLI
PUSH Push onto stack PUSH Source
PUSHF Push flags PUSHF
PUSHA Push all general registers PUSHA
POP Pop from stack POP Dest
POPF Pop flags POPF
POPA Pop all general registers POPA
CBW Convert byte to word CBW
CWD Convert word to double CWD
CWDE Conv word extended double CWDE
IN Input IN Dest, Port
OUT Output OUT Port, Source

ARITHMETIC
Name Comment Syntax
ADD Add ADD Dest,Source
ADC Add with Carry ADC Dest,Source
SUB Subtract SUB Dest,Source
SBB Subtract with borrow SBB Dest,Source
DIV Divide (unsigned) DIV Op
IDIV Signed Integer Divide IDIV Op
MUL Multiply (unsigned) MUL Op
IMUL Signed Integer Multiply IMUL Op
INC Increment INC Op
DEC Decrement DEC Op
CMP Compare CMP Op1,Op2
SAL Shift arithmetic left SAL Op,Quantity
SAR Shift arithmetic right SAR Op,Quantity
RCL Rotate left through Carry RCL Op,Quantity
RCR Rotate right through Carry RCR Op,Quantity
ROL Rotate left ROL Op,Quantity
ROR Rotate right ROR Op,Quantity

LOGIC
Name Comment Syntax
NEG Negate (two-complement) NEG Op
NOT Invert each bit NOT Op
AND Logical and AND Dest,Source
OR Logical or OR Dest,Source
XOR Logical exclusive or XOR Dest,Source
SHL Shift logical left SHL Op,Quantity
SHR Shift logical right SHR Op,Quantity

MISCELLANEOUS
Name Comment Syntax
NOP No operation NOP
LEA Load effective adress LEA Dest,Source
INT Interrupt INT Nr

JUMPS (general)
Name Comment Syntax
CALL Call subroutine CALL Proc
JMP Jump JMP Dest
JE Jump if Equal JE Dest
JZ Jump if Zero JZ Dest
JCXZ Jump if CX Zero JCXZ Dest
JP Jump if Parity (Parity Even) JP Dest
JPE Jump if Parity Even JPE Dest
RET Return from subroutine RET
JNE Jump if not Equal JNE Dest
JNZ Jump if not Zero JNZ Dest
JECXZ Jump if ECX Zero JECXZ Dest
JNP Jump if no Parity (Parity Odd) JNP Dest
JPO Jump if Parity Odd JPO Dest

JUMPS unsigned (Cardinal)
JA Jump if Above JA Dest
JAE Jump if Above or Equal JAE Dest
JB Jump if Below JB Dest
JBE Jump if Below or Equal JBE Dest
JNA Jump if not Above JNA Dest
JNAE Jump if not Above or Equal JNAE Dest
JNB Jump if not Below JNB Dest
JNBE Jump if not Below or Equal JNBE Dest
JC Jump if Carry JC Dest
JNC Jump if no Carry JNC Dest

JUMPS signed (Integer)
JG Jump if Greater JG Dest
JGE Jump if Greater or Equal JGE Dest
JL Jump if Less JL Dest
JLE Jump if Less or Equal JLE Dest
JNG Jump if not Greater JNG Dest
JNGE Jump if not Greater or Equal JNGE Dest
JNL Jump if not Less JNL Dest
JNLE Jump if not Less or Equal JNLE Dest
JO Jump if Overflow JO Dest
JNO Jump if no Overflow JNO Dest
JS Jump if Sign (= negative) JS Dest
JNS Jump if no Sign (= positive) JNS Dest

'Programing > asm' 카테고리의 다른 글

어셈블리어  (0) 2011.11.29
OpCode of Intel Assembly 80x86  (0) 2011.03.07
Posted by 패스맨

댓글을 달아 주세요