::NPTEAM:: Network Programer Team

검색 :
RSS 구독 : 글 / 댓글 / 트랙백 / 글+트랙백

MMORPG에서 좁은 지역에 유저 N명이 모여 있을 때 처리 방법

MMORPG에서 좁은 지역에 유저가 N명이 모여 있을 때 처리 방법
(출처 : http:://www.npteam.net/855)

1. 기획적 의도로 해결하는 방법

  • 국지전이 일어나는 장소를 여러 곳으로 분할한다.
  • 국지전에 참여할 수 있는 최대 인원수를 제한한다.

2. 프로그램적으로 해결하는 방법

  • 영향을 미치는 요소들
    • 데이터 크기
    • 데이터를 보내는 빈도 수
    • 전송 특성
      • 1:1 패킷 보내기
      • 1:N 패킷 보내기
      • N:M 패킷 보내기
  • 해결방법
    • 데이터 크기
      • 패킷 데이터의 크기를 최대한 줄인다.
        • 패킷에 포함된 기본 정보 단위를 최소화 한다.
          (
          자료형 단위를 줄이는 방법, 불필요한 정보를 제거하는 방법 )
      • 패킷 데이터를 압축한다.
        • 패킷 데이터를 압축/해제시 CPU 자원을 사용한다.
        • 브로드캐스팅할 경우 패킷이 작아지면 트래픽이 줄어드는 잇점이 있다.
                      
    • 데이터를 보내는 빈도 수
      • 최대 빈도수를 정한다.
        • 클라이언트 응답 속도 250ms일 경우 1초에 4
        • 클라이언트 응답 속도 200ms일 경우 1초에 5
          (
          이동 패킷과 스킬 사용 패킷을 1초에 4-5번으로 해결하기 어렵다.)
      • 우선순위 큐를 이용한 패킷 전송
        • 전투 관련 패킷을 우선적으로 처리한다.
        • 비우선 패킷들 : 로그, 채팅, 환경 오브젝트 처리
      • 이미 전송한 명령은 Send 버퍼 Queue에서 삭제한다.
        • 동일한 좌표로 계속 이동하는 패킷은 클라이언트에서 한번만 보내도 된다.
        • 필요 없는 패킷을 제거하여, 트래픽도 줄이고 서버의 CPU 자원 사용도 줄일 수 있다.
             
    • 전송 특성
      • 1:1 패킷 보내기
        • 문제점 없음
      • 1:N 패킷 보내기
        • Send 패킷 버퍼 재활용 필요함.
      • N:M 패킷 보내기
        • 패킷 압축 필요함.
        • Send 패킷 버퍼 재활용 필요함.
        • 브로드캐스팅을 게임 서버에서 하지 않고, Front 혹은 Agent 서버로 패스하여 처리한다.
          (UDP SuperPeer
          를 사용할 경우 클라이언트에서 브로드 캐스팅하는 것도 고려해 볼 수 있다.)

3. 그외에 더 생각해 볼 사항

  • CPU 자원
    • 메모리간 데이터 복사를 최소화 한다.
      • C++0x std::move를 사용하여 데이터 값 복사를 줄인다.
      • Reference Count 기능을 가진 패킷 컨테이너를 사용한다.
    • 메모리간 데이터 복사를 빠르게 한다.
      • FastMemcpy와 같이 CPU의 기본 레지스터 이외의 MMX와 같은 크기가 큰 레지스터에 데이터를 unrolling 하여,
        Loop
        를 이용한 데이터 복사 속도 저하를 개선한다
        .
             
  • 네트워크 자원
    • 보장이 필요한 패킷과 보장이 필요 없는 패킷으로 구분하여 처리한다.
      • 보장이 필요한 패킷 : 주기적인 시간 간격으로 동기화에 필요한 중요한 정보
        ) X, Y, Z, 좌표 + Angle
      • 보장이 필요 없는 패킷 : 주기적인 시간 간격보다 짧은 간격이면서, 손실되어도 문제 없는 정보
        ) Angle 정보
    • 보장이 필요한 패킷은 TCP로 보내고, 보장이 필요 없는 패킷은 UDP로 나누어 처리할 수 있다.
      (
      , 중국의 경우 UDP가 불가능한 상황도 발생한다
      .)
          
  • 브로드 캐스팅을 주체하는 서버를 구분한다.
    • Game 서버가 모든 패킷을 브로드캐스팅 하면, Front 혹은 Agent 서버에 N번의 요청을 전달한다.
    • 브로드캐스팅이 필요한 패킷을 각 Front 혹은 Agent 서버에 1회만 보내고(받을 클라이언트 목록을 함께), Front 혹은 Agent 서버에서 처리한다면,
      Game
      서버에서 N번 요청에 대한 CPU 자원 사용을 줄이고, 내부 네트워크 트래픽도 감소한다
      .
          
  • 유저 상태에 대한 패킷 처리
    • 유저가 전투 상태일 경우 패킷을 먼저 처리하고,
      비 전투 상태일 경우 나중에 처리하도록 한다
      .
      ) 마을에 모인 유저인 경우, 패킷이 늦게 처리되어도 문제가 발생하지 않는다.
2011/08/03 01:52 2011/08/03 01:52

맨 위로

JIRA 이슈 트래커 설치하기

JIRA는 이슈(Issue)를 관리하는 웹 기반 소프트웨어 입니다.

JIRA를 설치하기 위해서 http://www.atlassian.com/software/jira/에서 JIRA를 다운로드 합니다.
사용자 삽입 이미지
Windows용 JIRA를 다운 받으시고 설치를 합니다.
처음 설치하실 때에는 다음 버튼을 눌러서 설치하시고,
이미 설치되어 있는 경우에는 다음 단계에서 주의 하셔야 합니다.

사용자 삽입 이미지
위 메시지가 나올 경우에는 이미 JIRA가 한번 설치된 상황이므로,
설치를 중지하고 데이터 백업이 올바르게 되었는지 다시 한번 확인합니다.

처음 설치하신다면 위 메시지 박스가 나오지 않습니다.
다음과 같이 진행됩니다.
사용자 삽입 이미지
서비스 모드로 설치할 경우에는 Local System 계정으로 실행됩니다.
잘 모르실 경우에는 다음을 누르시면 됩니다.
사용자 삽입 이미지
마지막까지 잘 오셨습니다.

JIRA 제목을 입력하시고, 발급 받으신 라이센스 키를 입력합니다.
사용자 삽입 이미지

JIRA를 관리하는 관리자 계정 정보를 입력합니다.
사용자 삽입 이미지

이메일 알림을 받을지 설정하는 페이지 입니다.
알림을 받지 않으실 경우 Disable Email Notifications 버튼을 누르고 진행합니다.
사용자 삽입 이미지

이제 모든 설치가 끝났습니다.
사용자 삽입 이미지

위에서 추가한 관리자 계정으로 로그인 하시면 JIRA를 사용하실 수 있습니다.
2011/06/14 04:18 2011/06/14 04:18

맨 위로

프로그램은 왜 실패하는가? (발표자료)

아키텍트를 꿈꾸는 사람들에서 진행하는 토요일 스터디.
발표 자료입니다.

프로그램은 왜 실패하는가
View more presentations from zone0000.
2009/07/25 00:12 2009/07/25 00:12

맨 위로

Effective C++ 공부중(요약)

1장 C++에 왔으면 C++의 법에 따릅시다.

#1. C++을 언어들의 연합체로 바라보는 안목은 필수

 C++은 다중 패러다임 프로그래밍 언어이다.
 +---- 절차적(procedural) 프로그래밍
 |
 +---- 객체지향(object-oriented)
 |
 +---- 함수식(functional)
 |
 +---- 일반화(generic)프로그래밍
 |
 +---- 메타프로그래밍(metaprogramming)

 C++의 하위언어
 +---- C :
 |
 +---- 객체 지향 개념의 C++ : 클래스, 캡슐화, 상속, 다형성, 가상함수(동적 바인딩)
 |
 +---- 템플릿 C++
 |
 +---- STL : 컨테이너(container), 반복자(iterator), 알고리즘(algorithm), 함수 객체(function object)
 
#2. #define을 쓰려거든 const, enum, inline을 떠올리자
 선행처리자(pre-complier)보다 컴파일러를 더 가까이하자.
 
 (1) 매크로 대신 상수를 쓰자.
 #define ASPECT_RATIO 1.653
 --> const double AspectRation = 1.653;
 
 코드에서 숫자상수로 바뀌기 때문에, 기호 테이블(symbolic table)에 등록되지 않는다.
 
 const char* const authorName = "Sccot Meyers";
 const std::string authorName("Sccot Meyers");
 
 (2) 클래스 맴버로 상수를 정의하는 경우
 class CSomething{
  static const int NumTurns = 5;
 };
 static 멤버로 만든다. -> 유효영역이 클래스영역으로 제한되어 캡슐화에 용이하다.

 선언 방법
 a. 정적 맴버 변수가 정수형일 경우에는 선언과 동시에 초기화 가능
 b. 그외의 타입은 구현부분에서 초기화

 class CSomething {
  static const double FudgeFactor;
 };
 const double CSomething::FudgeFactor = 1.35;


 (3) enum 나열자 둔갑술
 나열자(enumerator)타입은 int가 놓일 곳에도 쓸 수 있다.
 
 예) 배열의 크기를 정의할때
 class CSomething {
 private:
  enum { NumTurns = 5 };
 
  int scores[NumTurns];
 };
 
 #define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
 
 int a = 5, b = 0;
 CALL_WITH_MAX( ++a, b );
 
 template <typename T>
 inline void callWithMax(const T& a, const T& b)
 {
  f(a > b ? a : b);
 }

#3. 낌새만 보이면 const를 들이대 보자!
 char greeting[] = "Hello";
 
 const char *p = greeting; // 상수 데이터, 비상수 포인터
 char * const p = greeting; // 비상수 데이터, 상수 포인터
 
 const <- * : 데이터
 * -> const : 포인터
 
 void f1(const Widget *pw); == void f1(Widget const *pw);
 // 둘다 같은 용법이다. * 왼쪽에 const는 마음데로 위치할 수 있다.
 
 std::vector<int> vec;
 
 const std::vector<int>::iterator iter = vec.begin();
 *iter = 10;  // 데이터 수정 가능
 ++iter;   // iterator 변경 불가능

 std::vector<int>::const_iterator cIter = vec.begin();
 *cIter = 10; // 데이터 수정 불가능
 ++iter;   // iterator 변경 가능
 
#4. 객체를 사용하기 전에 반드시 그 객체를 초기화 하자.
 직접 초기화, 생성자 초기화
 C++ 규칙 어떤 객체이든 그 객체의 데이터 맴버는 생성자의 본문이 "실행되기 전"에 초기화 되어야 한다.
 
 초기화 순서
 1. 기본 클래스는 파생클래스 보다 먼저 초기화된다.
 2. 클래스 데이터 맴버는 선언된 순서대로 초기화된다.
 3. 정적 객체의 초기화 순서는 개별 번역 단위에서 정해진다.
    (--> 초기화 시점이 달라질수 있으므로 싱글턴 패턴을 이용하여 해결하자)
   
   
2장 생성자, 소멸자 및 대입연산자

#5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자.
 클래스에 선언하지 않으면 컴파일러가 저절로 선언해 주는 것.
 1. 복사 생성자
 2. 복사 대입 연산자
 3. 소멸자
 
 class Empty{
 public:
  Empty() {}        // 기본생성자
  Empty(const Empty& rhs) {}    // 복사생성자
  ~Empty() {}        // 소멸자
 
  Empty& operator=(const Empty& rhs){} // 복사 대입 연산자
 };
 
 Empty e1;         // 기본생성자, 소멸자
 
 Empty e2(e1);        // 복사 생성자
 
 e2 = e1;         // 복사 대입 연산자
 
 암시적인 복사 대입연산자를 사용하지 못하도록 하는 방법
 기본 클래스에서 복사 대입 연산자를 private로 선언하면,
 파생 클래스에서 암시적 복사 대입 연산자를 가질수 없다.
 
#6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자.
 HomeForSale h1;
 HomeForSale h2;
 
 HomeForSale h3(h1);  // 복사생성자 컴파일 금지
 h1 = h2;    // 복사 대입 연산자 컴파일 금지
 
 해결방법 : 컴파일러가 생성하는 함수는 모두 공개된다.
 private로 복사생성자와 복사대입연산자를 선언하면 컴파일러는 자동 생성을 할 수 없다.
 명시적 선언을 하면 컴파일러는 자동생성을 하지 않고, private로 선언했으므로 외부에서 접근 불가.
 
 friend 접근까지 막으려면, 함수를 선언만 하고 정의하지 않으면 된다.
 class HomeForSale {
  HomeForSale(const HomeForSale&); // 선언만 딸랑하고 인자값도 넣지 않는다.
  HomeForSale& operator = (const HomeForSale&);
 };
 위와 같이 하면 링크시점에서 에러 발생
 
 컴파일 시점 에러발생을 하려면, 기본 클래스를 상속받으면 된다.
 class Uncopyable {
 protected:
  Uncopyable() {}
  ~Uncopyable() {}
 
 private:
  Uncopyable(const Uncopyable&);
  Uncopyable& operator = (const Uncopyable);
 };
 이 클래스를 상속 받으면 된다.(public 상속이 아니어도 된다.)
 class HomeForSale : private Uncopyable {
 };
 
#7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자.
 다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 한다.
 기본클래스가 아니거나 다형성이 필요없는 클래스에서 가상 소멸자를 선언하지 말자!
 
#8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자.
 예외 발생가능성이 있는 코드는 보통함수에서 깔끔하게 처리한다.
 소멸자에서 예외 발생 가능성이 포함된 코드실행 및 함수호출은 하지 않는다.
 
 소멸자에게 예외처리를 맡기지 말자.
 
#9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자.
 
 이부분은 넘어가자
 
#10. 대입 연산자는 *this의 참조자를 반환하게 하자.
 관례적인 성향이 있는 규칙( =, +=, -=, *=, /=, <<, >> )
 class Widget {
 public:
  Widget& operator=(const Widget& rhs)  // 반환타입은 클래스의 참조자
  {
   return *this;       // 좌변 객체의 참조자를 반환합니다.
  }
 };
 
#11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자.
 // 사본을 만들어 바꿔치기 한다.
 Widget& Widget::operator=(const Widget &rhs)
 {
  Widget temp(rhs);
 
  swap(temp);
 
  return *this;
 }
 
 // 명확성은 떨어지나 기술적인 코드
 Widget& Widget::operator=(Widget rhs) // 값에 의한 전달로 사본 전달
 {
  swap(rhs);
 
  return *this;
 }
 
#12. 객체의 모든 부분을 빠짐없이 복사하자.
 복사 생성자, 복사 대입 연산자.
 class PriorityCustomer : public Customer {
 };
 
 // 복사생성자 처리
 PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
 : Customer(rhs),      // 기본클래스의 복사 생성자를 호출합니다.
   priority(rhs.priority)
 {
 }
 
 // 복사 대입 연산자 처리
 PriorityCustomer& PriorityCustomer::operator =(const priorityCustomer& rhs)
 {
  Customer::operator=(rhs);   // 기본 클래스 부분을 대입합니다.
 }


3. 자원관리

#13. 자원관리에는 객체가 그만!
 std::auto_ptr<Investment> pInv(createInvestment());
 (1) 자원을 획득한 후에 자원 관리 객체에게 넘긴다.
 (2) 자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 합니다.
 
 참조 카운팅 방식 스마트 포인터(refrence-counting smart porinter: RCSP)
 std::tr1::shared_ptr<Investment> pInv(createInvestment());
 
#14. 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자.
 자원 획득 즉 초기화(RAII : Resource Acquisition Is Initialization)기법
 RAII 객체가 복사될 때 어떤 동작이 이루어져야 할까요?
 1. 복사를 금지합니다.
  class Uncopyable을 상속 받는다.
 2. 관리하고 있는 자원에 대해 참조 카운팅을 수행합니다.
  tr1::shared_ptr 이용
 3. 관리하고 있는 자원을 진짜로 복사합니다.
  깊은복사(Deep copy)로 모두 복사
 4. 관리하고 있는 자원의 소유권을 옮깁니다.
  auto_ptr의 복사 동작(swap)
 
#15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자.
 자원관리 클래스의 자원을 참조하여 사용할 수 있어야 한다.
 자원 변환 방법
 (1) 명시적 변환
 (2) 암시적 변환
 맞게 쓰기는 쉽게, 틀리게 쓰기는 어렵게 하자.
 std::string str;
 str.c_str();  // 명시적인 변환을 사용하면 암시적인 변환보다 편하진 않지만, 꼭 필요한 곳에서 맞게 쓸 수 있다.

#16. new 및 delete를 사용할때는 형태를 반드시 맞추자.
 CSomething pSomething = new CSomething;
 delete pSomething;
 
 std::string *stringArray = new std::string[100];
 delete [] stringArray;
 
#17. new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자.
 스킵

2009/07/22 21:51 2009/07/22 21:51

맨 위로

tolua++ 사용법


출처는 위와 같다. 웹 서핑을 하다가 Lua에 대해서 관심 있게 보는 도중..

눈에 띄는 블로그를 발견하였다.

tolua++이란 c++로 작성된 클래스를 루아에서 바로 접근 할수 있도록 지원해주는 일종의 툴이다.

이 한마디에 끌렸다고나 할까? ㅎㅎ

블로그 저작권을 침해하지 않기 위해서 참조만 링크하도록 한다.

원문은 링크를 찾아가서 보세요~~

windows용 tolua++ 툴 & 라이브러리 (vs8용 x86, x64)



tolua++ 홈페이지
http://www.codenix.com/~tolua/

tolua 매뉴얼
http://www.tecgraf.puc-rio.br/~celes/tolua/tolua-3.2.html
2007/07/08 04:03 2007/07/08 04:03

맨 위로

CRT 이야기


CodeWiz님의 블로그. 역시나 유용한 기사가 많다.

마이크로 소프트웨어 탭에 있는 기사들을 보려고 마음 먹었는데,

PDF로 되어 있는 기사와 DOC로 되어 있는 것이 대부분이라.

간편하게 웹에서 볼 수 있는 걸 찾던 중 CRT이야기가 낙찰(?) 되었다.

역시나 기본적인 내용 - 멀티 스레드, 멀티스레드 DLL에 표가 나와 있었다.

CRT에 왜 싱글 스레드, 멀티 스레드, 멀티 스레드 DLL 버전이 나오게 되었는지 모르는 분들을 위해서 간단히 말씀드리면, 예전에는 싱글 스레드 프로그래밍으로도 충분히 프로그램 제작이 가능하였다.

입출력이 동기화가 되었던 시절(DOS 운영체제를 썼던 그 시절 ㅎㅎ)에는 싱글 스레드로도 충분히 원하는 작업을 할 수 있었다. 그러나 윈도우로 넘어오면서 여러가지 일을 동시에 하고 싶을때 비동기적인 작업을 처리하기 위해서 스레드 프로그래밍이 필요하게 되었고, 이때 문제가 발생했다.

strtok와 같은 함수들은 static변수에 진행에 필요한 값을 저장하는데, 멀티 스레드에서는 스레드 마다 변수가 존재하지 않기 때문에(즉, 여러 스레드가 하나의 변수를 공유해서 쓰기 때문에) strtok와 같은 CRT 함수들을 사용하는데 있어서 치명적인 문제점이 발생하였다.

이 문제를 해결하기 위해서 멀티 스레드, 멀티 스레드 DLL 용 CRT가 나온것으로 알고 있으나, 제가 알고 있는게 틀릴 가능성도 있으므로 맹목적으로 신뢰하지 말아주세요. ㅎㅎ

다시 Codewiz님의 블로그 내용으로 넘어가서 exe와 dll 모듈에서 메모리 할당이 각각 이루어 질 수 있다는 사실은 이번에 처음 알게 되었네요.(왠지 제가 쓴글에 비해서 Codewiz님의 말씀은 100% 믿을 수 있을것 같은 느낌이 들어요 *_*)

바쁘실텐데도 다른 개발자 분들을 위해서 노력해주시는 CodeWiz님께 다시 한번 감사 드립니다.


비주얼 스튜디오 2005에서는 다음과 같이 안정화된 CRT 함수들을 제공한다.
Security-Enhanced Versions of CRT Functions 
http://msdn2.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

printf Type Field Characters
http://msdn2.microsoft.com/en-us/library/hf4y5e3w(VS.80).aspx

CRT 함수중 _snprintf_s 와 같이 가변인자 파라매터(%s, %c) 문서
2007/07/04 09:03 2007/07/04 09:03

맨 위로

Enumerating Windows Processes(프로세스 목록 보기)


프로세스 목록을 보기 위한 5가지 방법을 제시하고 있는 아티클이다.
2007/01/21 14:53 2007/01/21 14:53

맨 위로

HRESULT 가 뭐냐?

출처 : http://blog.naver.com/hopal78/100013977424

HRESULT

The HRESULT data type is a 32-bit value that is used to describe an error or warning.

typedef LONG HRESULT; 

Remarks

On 32-bit platforms, the HRESULT data type is the same as the SCODE data type. On 16-bit platforms, an SCODE value is used to generate an HRESULT value.

An HRESULT value is made up of the following fields:

  • A 1-bit code indicating severity, where zero represents success and 1 represents failure.
  • A 4-bit reserved value.
  • An 11-bit code indicating responsibility for the error or warning, also known as a facility code.
  • A 16-bit code describing the error or warning.

========================================================================================

아래는 winerror.h에 나온 SCODE, HRESULT내용 입니다

퍼실리티(Facility)와 리턴코드(Return Code)에 관련된 상태코드에 대한 내용은 <winerror.h>에 정의되어 있으며

========================================================================================

////////////////////////////////////
//                                                //
//     OLE Error Codes                   //
//                                                //
////////////////////////////////////

//
// OLE error definitions and values
//
// The return value of OLE APIs and methods is an HRESULT.
// This is not a handle to anything, but is merely a 32-bit value
// with several fields encoded in the value.  The parts of an
// HRESULT are shown below.
//
// Many of the macros and functions below were orginally defined to
// operate on SCODEs.  SCODEs are no longer used.  The macros are
// still present for compatibility and easy porting of Win16 code.
// Newly written code should use the HRESULT macros and functions.
//

//
//  HRESULTs are 32 bit values layed out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +-+-+-+-+-+---------------------+-------------------------------+
//  |S|R|C|N|r|    Facility         |               Code            |
//  +-+-+-+-+-+---------------------+-------------------------------+
//
//  where
//
//      S - Severity - indicates success/fail
//
//          0 - Success
//          1 - Fail (COERROR)
//
//      R - reserved portion of the facility code, corresponds to NT's
//              second severity bit.
//
//      C - reserved portion of the facility code, corresponds to NT's
//              C field.
//
//      N - reserved portion of the facility code. Used to indicate a
//              mapped NT status value.
//
//      r - reserved portion of the facility code. Reserved for internal
//              use. Used to indicate HRESULT values that are not status
//              values, but are instead message ids for display strings.
//
//      Facility - is the facility code
//
//      Code - is the facility's status code
//

//
// Severity values
//



번역


HRESULT 형의 구조
0~15 비트 : RETURN CODE
16~28 비트 : FACILITY
29~30 비트 : R
31 비트 : SEVERITY

SEVERITY(31비트)는 함수의 수행의 성공과 실패를 알려주는 코드다. 를 검사하기 위해서는 다음 예제코드와 같이 SUCCEEDED 혹은 FAILED 매크로를 사용해야 한다.

//SUCCEEDED 경우
   ICalc* pICalc = NULL;

   HRESULT hr = pI->QueryInterface(IID_ICalc, (void**)&pICalc);
   if (SUCCEEDED(hr)) {
       pICalc->Add();
   }
   pICalc->Release();

//FAILED 경우
   HRESULT hr;
   hr = ::CoInitialize(NULL);
   if(FAILED(hr)) {
       AfxMessageBox("COM 라이브러리를 초기화할 수 없다.");
       return FALSE;
   }

< 상태코드 요약 >
S_OK : 때때로 Boolean TRUE 값(0X0)으로 S_FALSE와 함께 사용되며 함수가 성공하였음을 의미한다.

NOERROR : S_OK와 동일한 의미이다.

S_FALSE : S_OK와 반대로 Boolean FALSE 값(0X1)으로 함수가 실폐하였음을 의미한다.

E_UNEXPRCTED : 치명적인 실패를 의미한다.

E_NOTIMPL : 멤버 함수에 구현 코드가 포함되어 있지 않다.

E_OUTOFMEMORY : 필요한 메모리를 할당할 수 없음

E_INVALIDARG : 하나 혹은 그 이상의 인자가 타당하지 않음

E_NOINTERFACE : 요청한 인터페이스를 지원하지 않음

E_POINTER : 타당하지 않은 포인터

E_HANDLE : 타당하지 않은 처리

E_ABORT : 작동 중지

E_FAIL : 특정하지 않은 실패

E_ACCESSDENIED : 일반적 접근이 금지된 에러


///////////////////////////////////////////////////////////////////////

5.2.2 HRESULT

COM 인터페이스에 소속된 대부분의 함수들은 HRESULT형의 값을 반환하고 있는 데, 멤버 함수들이 이러한 HRESULT형의 값을 반환하는 것은 COM의 규정에 의한 것은 아니다.

그러나 이와 같이 COM 인터페이스에 소속된 대다수 멤버 함수들이 HRESULT형을 반환하면, 클라이언트에게 컴포넌트의 멤버 함수들의 수행과 관련한 상태정보를 일관된 방법으로 반환하게 해주는 결과가 될 것이며, 또한 COM의 하부 시스템에서 발생하는 오류들에 대한 정보를 전달할 수 있게 한다.

즉 COM의 하부 시스템이 아파트먼트(Apartment), 프로세스, 시스템 등의 경계를 가로질러 구성되면, 이러한 하부 시스템은 멤버 함수의 호출에 개입하게 된다. 이때 멤버 함수의 반환 자료형으로 HRESULT형을 사용하면 하부 시스템에서 발생하는 오류들에 대한 정보들을 호출자 즉 클라이언트에게 전달해 줄 수 있다.

2006/10/23 23:12 2006/10/23 23:12

맨 위로

Visual Leak Detector - Enhanced Memory Leak Detection for Visual C++

출처 : http://conv2.com/blog/index.php?pl=366&ct1=9&ct2=26

Visual Leak Detector - Enhanced Memory Leak Detection for Visual C++

Visual C++로 프로그램을 짜다보면 마주치는 게 메모리 릭(Memory Leak)이다. 특히 라이브러리와 연동할 때, 자기가 짠 프로그램에 문제가 있는지 아니면 라이브러리에 문제 있는 건지 판단하기가 힘들 때, 메모리 할당/해제를 빼먹은 거 같은데, 어디에 있는지 모를 때는 Visual Leak Detector 라는 프로그램이 도와줄 것이다.

Visual C++ provides built-in memory leak detection, but its capabilities are minimal at best. This memory leak detector was created as a free alternative to the built-in memory leak detector provided with Visual C++. Here are some of Visual Leak Detector's features, none of which exist in the built-in detector:

* Provides a complete stack trace for each leaked block, including source file and line number information when available.
* Provides complete data dumps (in hex and ASCII) of leaked blocks.
* Customizable level of detail in the memory leak report.

Other after-market leak detectors for Visual C++ are already available. But most of the really popular ones, like Purify and BoundsChecker, are very expensive. A few free alternatives exist, but they're often too intrusive, restrictive, or unreliable. Here are some key advantages that Visual Leak Detector has over many other free alternatives:

* Visual Leak Detector is cleanly packaged as an easy-to-use library. You don't need to compile its source code to use it. And you only need to make minor additions to your own source code to integrate it with your program.
* In addition to providing stack traces with source files, line numbers, and function names, Visual Leak Detector also provides data dumps.
* It works with both C++ and C programs (compatible with both new/delete and malloc/free).
* The full source code to the library is included and it is well documented, so it is easy to customize it to suit your needs.
Visual Leak Detector is licensed free of charge as a service to the Windows developer community.


Visual Leak Detector를 자신이 사용하는 프로젝트에 적용하는 법은 매우 간단하다.

vld-10.zip

Visual Leak Detector 1.0

위 vld-10.zip을 풀어보면 다음과 같은 파일 목록을 갖고 있을 것이다. 여기서 빨갛게 동그라미 친 부분인 3개 파일에 주목하자.


먼저, 프로젝트가 있는 곳을 $(PROJECT)라고 가정한다. vld.lib와 dbghelp.dll 등 두 개 파일을 $(PROJECT)/Debug 에 복사한다.

그 다음으로 vld.h를 $(PROJECT)에 복사한 후, Visual Studio에서 적절한 헤더 파일을 열어 #include "vld.h"를 추가한다. conv2군의 경우는 StdAfx.h에 추가하였다.

위와 같이 라이브러리 파일 복사하고 헤더 파일을 삽입하는 게 전부일 정도로 매우 쉽다는 것을 알았을 것이다. 그리고 이제 Rebuild 해서, 프로그램 메뉴를 선택하여 임의로 수행한 후 종료하면 디버그 창에 스택 위치와 관련한 메시지가 나타날 것이다. 물론 메모리 릭이 나는 프로그램이어야 하겠지만... 일단 메모리 릭에 걸려버리면 Visual Leak Detector가 감지해서 디버그 창으로 메세지를 보내준다.

사용자 삽입 이미지

Call Stack 밑에 해당 소스 파일명이 나타나므로, 메모리 릭이 어디서 발생했는지 쉽게 알 수 있을 것이다. 또한 소스 파일명을 클릭하면 해당 소스로 위치 시켜주므로 매우 편리하다. 이제, 메모리 릭의 공포에서 벗어날 수 있게끔 도와주는 Visual Leak Detector를 멋지게 활용 하길 바란다. ^^;

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

* 참고 : Visual Leak Detector가 Visual Studio 계열에서만 가능하다면, 리눅스에서는 Valgrind 가 있다. 실제로 Valgrind가 지원하는 플랫폼은 아래와 같다.

* x86/Linux: support is mature and almost complete.
* AMD64/Linux: support is new but fairly complete.
* PPC32/Linux: support is new, incomplete, but improving.

사용자 삽입 이미지

( 출처 : http://gogamza.cafe24.com/520 )
2006/10/09 22:29 2006/10/09 22:29

맨 위로

Windows 시간 관련 프로그래밍 정보

Edited by Dual(dual5651@hotmail.com)

이번글은 블로깅을 하면서 발견한 시간관련 글들을
종합하여 편집 함으로써 이부분에 대해 궁금해 하시는
분에게 도움이 되고자 해서 편집 & 작성하여 보았습니다.


1. Tick 구하기 - 1

타이머 문제로 골몰하다 멀티미디어 라이브러리의 바이너리를
뒤적거리기로 했다. 한참동안 winmm.lib 의 네이티브 코드를
뒤지다가 재미난 것을 한가지 발견. 일단 해당 부분을 뜯어
간단히 인라인 어셈으로 옮겨 보았다.

inline unsigned __int64 getMisteryCount()
{
  __asm  
  {  
    mov    edx,dword ptr ds:[7FFE000Ch]
    mov    eax,dword ptr ds:[7FFE0008h]
  }
}

아무런 문서도 없이 바이너리를 뒤지다 얻어낸 정보인지라
저 주소가 무엇을 의미하는지는 나도 모른다. 구글에도
없는것을 보니 완전한 un-documented feature 같다.

어쨌든 저 주소에는 1/10000 초 단위의 시간이 저장되어 있다.
물론 아래와 같이 10000 을 나누어 milli-second 단위로 변환해서
사용하는것도 가능하다.

inline unsigned int getElapsedMilliSecond()
{
  return static_cast< unsigned int >
  ( getMisteryCount()/10000 );
}

mov 를 두번 호출할 뿐인지라 속도는 경이적이다.
빠르지만 최악의 정밀도를 보여주는 GetTickCount()
보다도 4배정도 빠르다. 아무일도 하지 않고 루프만 돈
noproc() 에 거의 근접한다.



getMisteryCount() 와 getElapsedMilliSecond() 의
속도차이의 이유는 64-bit div 연산에 있다. 32-bit 프로세서에서
__int64 나누기를 하려면 수십개의 인스트럭션이 필요하다.
테스트 결과 getMisteryCount() 는 Win95/98/Me 등에선 동작하지
않는다. XP , 2000, 2003 등 NT 커널 기반 OS 에서만 돌아가는 듯
하다. 어쨌건 퍼포먼스 카운트용으로 이보다 더 좋은 타이머는
없을 듯 하다.

2. Tick 구하기 - 2

대부분 Speed Hack은 kernel.dll에 있는 GetTickCount()나
winmm.dll에 있는 timeGetTime() 함수를 조작해서 만들어 진다.
그러나 그러한 역할을 하는 걸 Win32API를 쓰지 않고 아래와 같은
ASM을 사용한다면 해결을 할 수 있지 않을까 싶다.

_asm
{
RDTSC
mov DWORD PTR iCurrentTick, eax
mov DWORD PTR iCurrentTick+ 4, edx
}

RDTSC 어셈은 8x86 CPU에 들어 있는 ASM이다.
CPU의 클럭값을 eax와 edx에 return하는 어셈이라
2개의 레지스터에서 메모리로 옮기면 GetTickCount()
역할을 할 수 있다.

3. Win32 환경에서의 타이머 종류

Ansi C의 time(), _ftime()

Ansi 표준 C 라이브러리의 함수들로,
time()은 최소 1초 단위의 값을 돌려준다.
메인 루프 제어용으로는 부적합하나 게임 저장
날짜/시간의 기록 등에는 유용할 것임.
_ftime()은 밀리초(1000분의 1초) 단위의 값을 돌려준다.

Win32 API의 timeGetTime() 함수

흔히 멀티미디어 타이머라고 하는 것으로,
윈도우즈가 시작된 이후 흐른 시스템 시간을 돌려준다.
단위는 밀리초. 기본 정밀도는 Win9x의 경우 1 밀리초,
NT 패밀리의 경우 5 밀리초 이상이라고 함.
이정도면 _ftime()과 함께 게임에서 써먹을 수 있을 만한 함수.

타이머의 해상도는 timeGetDevCaps()와
timeBeginPeriod()로 조정할 수 있다.

Win32 API의 WM_TIMER 메시지

일정한 시간 주기로 발생하는 메시지.
주기의 최소 단위는 역시 밀리초 단위.
메시지 펌프에서 잡거나 SetTimer()를 이용해서
콜백 함수를 호출하게 만들 수 있음.
그러나 메시지의 우선 순위가 낮기 때문에 정확하지 못하다.

Win32 API의 GetTickCount() 함수

시스템 틱 카운트를 돌려주며, 단위는 밀리초.
Win9x의 경우 기본 정밀도는 약 55 밀리초,
NT 급은 10에서 16 정도... timeGetTime()보다 못함...

고해상도 타이머

하드웨어가 고해상도 타이머를 지원하는 경우라면
가장 좋은 선택으로, 매우 정밀한 시간을 얻을 수 있다.
얻을 수 있는 시간의 해상도는 하드웨어마다 다르나,
어쨌든 적어도 위에 나온 것들보다는 정밀하다고 함.
관련 함수(자세한 사항은 MSDN 참고)

둘 다 windows.h만 포함시키면 됨...

BOOL QueryPerformanceCounter(
LARGE_INTEGER *lpPerformanceCount  // pointer to counter value
);

BOOL QueryPerformanceFrequency(
LARGE_INTEGER *lpFrequency  // address of current frequency
);

고해상도 타이머의 해상도 및 지원 여부 알아내기

QueryPerformanceFrequency(&ticksPerSecond)의 반환값이 0이
아니면 고해상도 타이머를 지원하는 것이다.
이 때 tickPerSecond에는 초 당 틱 수가 설정된다.

예:

LARGE_INTEGER ticksPerSecond;
if (!QueryPerformanceFrequency(&ticksPerSecond))
{
  // 지원하지 않음
  return false;
}

현재 시간 얻기

QueryPerformanceCounter(&ticks)를 호출하면 ticks에
성능 카운터 수(음.. 컴퓨터가 켜진 후 지나간 틱 수)가 설정된다.
이를 위에서 얻은 ticksPerSecond로 나누면 초
단위의 시간을 얻을 수 있다.

예:

LARGE_INTEGER ticks;
QueryPerformanceCounter(&ticks);

float seconds = ((float)ticks.QuadPart
            / (float)ticksPerSecond.QuadPart;


지나간 시간 얻기

게임에서 실제로 필요한 것은 이전 프레임으로부터 흐른 시간인데,
그냥 현재 시간에서 이전 시간을 빼면 됨...

예: float GetElapsedSeconds(unsigned long elapsedFrames = 1)
{
static LARGE_INTEGER s_lastTime = m_startTime;
LARGE_INTEGER currentTime;

QueryPerformanceCounter(&currentTime);

float seconds = ((float)currentTime.QuadPart -
      (float)s_lastTime.QuadPart) / (float)m_ticksPerSecond.QuadPart;

// reset the timer
s_lastTime = currentTime;

return seconds;
} // end GetElapsedSeconds()

QueryPerformanceCounter의 문제점

일부 메인보드/칩셋에서 시간이 건너뛴다는 보고가 있음.

RDTSC

인텔 펜티엄 계열 CPU에서 제공하는 어셈블리 명령이다.
펜티엄은 내부적으로 TSC(Time Stamp Counter)라는
64비트 카운터를 유지하는데 이 카운터의 값은 클럭
사이클마다 증가한다.
RDTSC 명령은 내부 TSC 카운터의 값을 EDX와 EAX 레지스터에
복사하는 명령이다.
이 명령은 6~11 클럭을 소요한다. 고해상도 타이머가
이 명령을 이용해 구현되었다고 한다.

시간에 기반한 게임 갱신


고정 시간 간격

한 프레임에 걸리는 시간을 고정시키는 것.
간단히 말하면, 한 프레임에 걸리는 표준 목표
시간을 설정하고, 한 프레임에 걸린 시간이 그보다
작으면 남는 부분만큼 아무 일도 하지 않고 기다리는 것이다.

의사코드:

게임 메인 루프
{
      현재시각을 얻는다.

      한 프레임 처리;

      흐른시간 = 현재시각 - 아까 얻은 현재시각

      만일 ( 흐른시간 < 목표시간)
      {
        (목표시간 - 흐른시간)만큼 쉰다. //예: Sleep(...);
      }
}

장점: 시간 관리가 직관적이고 간편하다(시간 자체를 중심으로 바라볼 때).
또한 멀티미디어와의 시간 동기화가 편하다
(애니메이션과 배경음악/대사를 일치시키는 등).

단점: 한 프레임 처리에 걸린 시간이 목표시간보다 더 긴 경우 게임의 속도가
일정하지 않게 된다. 또한 최소 사양 이하의 컴퓨터라면 게임 전체가 느리게
돌아가게 된다.


가변 시간 간격

게임의 기능 및 객체들이 이전 프레임 이후 흐른 시간
(이하 프레임 시간)에 기반해서 갱신되게 하는 것.
예를 들어 어떤 객체가 1초당 10미터를 수평 이동
한다고 하면, 객체의 x 좌표는: x = x + 10 * (프레임 시간)
이렇게 하면 프레임 시간에 상관없이(즉 CPU 속도나 기타
다른 요인과 독립적으로) 객체는 항상 초 당 10 미터의
속력을 가지게 된다.

장점: 객체의 입장으로 바라볼 때 직관적.
게임을 실세계의 단위(미터, 초 등)에 기반해서 모델링할 때 크게 유용할 수 있다.

단점: 모든 객체들의 갱신 방식을 시간에 기반한 함수로 생각할 수 있어야 한다.
3D라면 당연하지만 전통적인 2D 게임이라면 사고의 전환이 필요함...

출처 : http://dual.inxzone.net/backup/blog/index.php?pl=184&ct1=1
2006/10/03 20:42 2006/10/03 20:42

맨 위로

Dress Your Applications for Success with WinInet


WinInet 에 관한 문서자료
2006/09/12 20:59 2006/09/12 20:59

맨 위로

WinInet 관련자료

1.요약

IE(Internet Explorer)같은 웹 브라우저를 이용하지 않고, 서버측에 있는 코드를 직접호출하는 방법에 대해서 알아보도록 합니다.


2.본문

웹 서버의 서버 코드를 직접실행하는 방법은 여러가지 단계를 거쳐야 합니다.

'서버 접근 --> 연결 --> 접속 확인 --> 메세지 보내기 --> 연결 닫기'

위의 방법을 다시 함수로 나누어 보면

(1) 서버 접근 : InternetOpen
(2) 서버 연결 : InternetConnect
(3) 접속 확인 : HttpOpenRequest
(4) 메세지 전송 : HttpSendRequest
(5) 연결 닫기 : InternetCloseHandle

이러한 과정을 거치는 작업에서 여럽다고 느껴지는 부분은 해당 함수에 전달해야 하는 인자값들인데, 다음의 예제를 보시면 더욱 이해가 빠르실거라고 생각합니다.

예전에, 이와 관련된 문서를 찾던중 가장 근접했던것이 VB 소스였는데, 아마 Platform SDK를 검색해 보시면 관련 예제를 찾으실 수 있을 것입니다.


3.예제



#include <Wininet.h>                // 필요한 헤더 파일
#pragma comment(lib, "wininet")     // 필요한 lib 파일


// 예제 함수

void CSendMsgToWebServerDlg::OnSend()
{

   // -----------------
   // Web 서버에 메세지 전송하기
   // -----------------
   // [ 중요 데이터 변수]
   //  - szServer : 서버의 주소(예, http://www.devpia.com)
   //  - szObject : 호출 문장 (예, /test/test.php3?table=t_talk&page=2)
   
   // 변수 선언 및 초기화
   HINTERNET hOpen, hConnect, hReq;
   INTERNET_PORT dwPort = INTERNET_INVALID_PORT_NUMBER;
   DWORD  dwFlags = INTERNET_FLAG_RELOAD |
       INTERNET_FLAG_NO_CACHE_WRITE |
       INTERNET_FLAG_KEEP_CONNECTION;
   CHAR szServer[256], szObject [20000];
   TCHAR szAccept[] = "*/*";
   LPSTR AcceptTypes[2]={0};
   
/*
   만약 다음의 주소를 호출하고자 한다면
   다음의 예와 같이 szServer 와 szObject를 나누어서 보내야 합니다.

   http://www.devpia.com/test/test.php3?table=t_talk&page=2    
*/

   strcpy(szServer, "http://www.devpia.com");
   wsprintf(szObject, "/test/test.php3?table=t_talk&page=2");
   
   // ~ 변수 선언 및 초기화
   
   
   // 핵심 함수 Call
   hOpen = InternetOpen (NULL,  LOCAL_INTERNET_ACCESS , NULL, 0, 0);
   hConnect = InternetConnect ( hOpen, szServer , dwPort, "",  "", INTERNET_SERVICE_HTTP, 0  , 0);
   
   hReq = HttpOpenRequest (hConnect, "GET", szObject, HTTP_VERSION, "",
       (LPCTSTR*) AcceptTypes, dwFlags ,0 );
   HttpSendRequest (hReq, NULL, 0, NULL, 0);
   
   
   // ~ 핵심 함수 Call
   
   
   // Handle 닫기
   InternetCloseHandle (hReq);
   InternetCloseHandle (hConnect);
   InternetCloseHandle (hOpen);
   // ~ Handle 닫기

}

2006/09/12 20:56 2006/09/12 20:56

맨 위로

서브버전 사용하기(Subversion)

출처 : http://blog.naver.com/kangse1016/100027164335

* 서브버전 내 컴퓨터에서 사용하기(윈도우)

1. 설치 순서

가. 설치파일 구하기

1) Subversion Windows 설치파일을 받아 설치한다.

http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91

(svn-1.3.2-setup.exe)

2) SVNSERVE Manager프로그램을 받아 설치한다.

http://www.pyrasis.com/main/SVNSERVEManager

(SVNManager-1[1].0.4-Setup.msi)

이 프로그램은 명령행에서 일일이 실행하는 불편함을 덜어주고, svnserve의 동작/정지 상태를 트레이 아이콘으로 표시해 주며 시스템 시작시 svnserve를 자동으로 실행하게 한다.

3) GUI 클라이언트 프로그램을 받아 설치한다.

http://tortoisesvn.tigris.org

(TortoiseSVN-1.4.0.7195-RC1-win32-svn-1.4.0RC1.msi)

(LanguagePack-1.4.0.7195-RC1-win32-ko.exe)

나. 루트폴더의 저장소를 하나 만든다.

다. SVNSERVE Manager로 지금 만든 저장소를 등록해서 실행시킨다.

라. GUI 클라이언트로 프로젝트 개념의 저장소를 하나 만든다. 이 저장소가 프로젝트를 관리한다.

마. 사용한다.


2. 용어들

가. 저장소

리포지토리(Repository)라고도 하며 모든 프로젝트의 프로그램 소스들은 이 저장소 안에 저장이 됩니다. 그리고 소스뿐만이 아니라 소스의 변경 사항도 모두 저장됩니다. 네트워크를 통해서 여러 사람이 접근 할 수 있습니다. 버전 관리 시스템 마다 각각 다른 파일 시스템을 가지고 있으며 Subversion은 Berkeley DB를 사용합니다. 한 프로젝트 마다 하나의 저장소가 필요합니다.

나. 체크아웃

장소에서 소스를 받아오는 것입니다. 체크아웃을 한 소스를 보면 프로그램 소스가 아닌 다른 디렉토리와 파일들이 섞여 있는 것을 볼 수 있습니다. 이 디렉토리와 파일들은 버전 관리를 위한 파일들입니다. 임의로 지우거나 변경하면 저장소와 연결이 되지 않습니다. 체크아웃에도 권한을 줄 수 있습니다. 오픈 소스 프로젝트들에서는 대부분 익명 체크아웃을 허용하고 있습니다.

다. 커밋(Commit)

체크아웃 한 소스를 수정, 파일 추가, 삭제 등을 한 뒤 저장소에 저장하여 갱신 하는 것입니다. 커밋을 하면 CVS의 경우 수정한 파일의 리비전이 증가하고 Subversion의 경우 전체 리비전이 1 증가하게 됩니다.

라. 업데이트(Update)

체크아웃을 해서 소스를 가져 왔더라도 다른 사람이 커밋을 하여 소스가 달라졌을 것입니다. 이럴 경우 업데이트를 하여 저장소에 있는 최신 버전의 소스를 가져옵니다. 물론 바뀐 부분만 가져옵니다.

마. 리비전(Revision)

소스 파일등을 수정하여 커밋하게 되면 일정한 규칙에 의해 숫자가 증가 합니다. 저장소에 저장된 각각의 파일 버전이라 할 수 있습니다. Subversion의 경우 파일별로 리비전이 매겨지지 않고 한번 커밋 한 것으로 전체 리비전이 매겨 집니다. 리비전을 보고 프로젝트 진행 상황을 알 수 있습니다.

바. 임포트(Import)

아무것도 들어있지 않은 저장소에 맨 처음 소스를 넣는 작업입니다.

사. 익스포트(Export)

체크아웃과는 달리 버전 관리 파일들을 뺀 순수한 소스 파일을 받아올 수 있습니다. 소스를 압축하여 릴리즈 할 때 사용합니다.


서브버전 사용하기(리눅스)
http://www.pyrasis.com/main/Subversion-HOWTO#s-1.1

Subversion을 사용하다가 가끔 특정리비젼의 로그메세지를 수정해야 할때가 있다.
아래는 윈도우용에서의 사용예이다.

수정하고자하는 프로젝트가 들어있는 저장소의 폴더중에 "hooks" 라는 폴더밑에 "pre-revprop-change.bat" 라는 파일을 만들고 아래의 내용을 넣고 저장한다

rem Only allow log messages to be changed.
if "%4" == "svn:log" exit 0
echo Property '%4' cannot be changed >&2
exit 1




TortoiseSVN-1.5.0.13316_Package.zip

TotoriseSVN 클라이언트 자동설치 패키지



출처 : http://www.jiniya.net/tt/540
CodeWiz님이 수정하신 Scintilla용 IME 패치
C:\Program Files\TortoiseSVN\bin 폴더에 덮어쓰기 하면 한글 IME 문제 해결


SVN Notifier 글 링크 : http://www.npteam.net/578

2006/08/31 16:59 2006/08/31 16:59

맨 위로

[C/C++] strcpy() & strncpy()

strncpy의 안정적인 사용법

strncpy( 목적지 buffer, 원본 pointer, sizeof( 목적지 buffer ) - 1 );
목적지 buffer[ sizeof( 목적지 buffer ) -1 ] = '\0';


strcpy

#include <string.h> 
char *strcpy(char *dest, const char *src);

  src가 가르키는 문자열을 dest가 가르키는 배열에 복사한다. src에서 복사될때 '\0' 까지 복사됨으로 문자열이 겹쳐지지는 않는다. 이때 dest는 src를 모두 복사 받을수 있을정도로 충분히 커야 한다.

strcpy()는 목적지의 배열의 크기가 충분히 크지 않을경우 어떤일이 발생될지 알 수가 없다. 운이 좋으면 세그먼트폴트 에러와 함께 죽겠지만, 그렇지 않고 알수 없는 작동을 할 수도 있다. 이는 흔히 말하는 버퍼 오버 플로우 크래커 기술에 매우 취약하다. strcpy()를 쓰기전에는 반드시 복사할 문자열의 크기를 검사해주어야 한다. 또는 strncpy()를 써야 한다.

반환값: 목적지 문자열 dest에 대한 포인터를 반환한다.

예제:

#include <string.h>
int main(int argc, char *argv[], char evnp[])
{
  char buffer[20];

  strcpy(buffer, "hello world");
  printf("%s\n", buffer);

  strcpy(buffer, "naver blog");
  printf("%s\n", buffer);

return 0;
}


원형:
static void strcpy(char *s, char *t)
{
     while ((*s = *t) !='\0')
    {
           s++;

            t++;
    }

    *s = '\0';
}

strncpy

#include <string.h>
char *strncpy(char *dest, const char *src, size_t n);

src가 가르키는 문자열을 dest가 가르키는 배열에 복사한다. src에서 복사될때 '\0' 까지 복사됨으로 문자열이 겹쳐지지는 않는다. 이때 dest는 src를 모두 복사 받을수 있을정도로 충분히 커야 한다.

strncpy()는 n을 이용해서 복사할 문자열의 크기를 정할 수 있으므로 버퍼 오버 플로우에 좀더 안전하다. 만약 src의 길이가 n 보다 작다면 dest의 남는 공간은null 로 채워진다.

반환값: 목적지 문자열 dest에 대한 포인터를 반환한다.

예제:

#include <string.h>
int main(int argc, char *argv[], char evnp[])
{
  char buffer[25];

  strncpy(buffer, "hello world", 25);
  printf("%s\n", buffer);


//strset(buffer, 0); //buffer 초기화
  strncpy(buffer, "naver blog", 5);
  printf("%s\n", buffer);

return 0;
}


strcpy(dest, src);과 strncpy(dest, src, sizeof(dest)-1); 은 절대 같지 않다.

  strcpy는 src의 널문자를 자동으로 복사하지만 (버퍼 오버플로우는 논외) strncpy는 파라미터 n개만 복사하고 널을 붙이지 않는다. 다만 src의 길이가 n보다 짧다면 dest에 갖다붙인 src뒤로 인덱스 n-1까지는 널로 채워준다.

  즉, 파라미터로 넘긴 n개 까지는 자기가 책임지지만,   만약 src의 길이가 딱 n개이거나 n보다 큰 경우에는 destination의 끝에 널이 붙지 않는다. 때문에 strncpy(dest, src, sizeof(temp)-1);문 다음행에 dest[sizeof(dest)-1]=0;을 반드시 추가한다.

#include <string.h>
int main(int argc, char *argv[], char evnp[])
{
  char buffer[25];  

  strncpy(buffer, "naver blog1", 7);
  printf("%s\n", buffer);   //naver b[儆儆儆儆儆儆儆儆儆儆儆儆??]쓰레기 값

  strncpy(buffer, "naver blog2", sizeof(buffer)-1);
   printf("%s\n", buffer);   //naver blog2

   strncpy(buffer, "naver blog3", 7);
   printf("%s\n", buffer);   ////naver b[log2]이전의 버퍼 값

   strcpy(buffer, "hello world");
   printf("%s\n", buffer);

  return 0;
}


출처 : http://blog.naver.com/cidsang/20032605

2006/08/16 03:17 2006/08/16 03:17

맨 위로

[Shell] CSIDL Values - 쉘 프로그래밍

CSIDL Values

There are a number of folders that are used frequently by applications, but may not have the same name or location on any given system. For example, the system folder may be "C:\Windows" on one system and "C:\Winnt" on another. CSIDL values provide a unique system-independent way to identify these special folders. They supersede the use of environment variables for this purpose.

A CSIDL is used in conjunction with one of four shell functions, SHGetFolderLocation, SHGetFolderPath, SHGetSpecialFolderLocation, and SHGetSpecialFolderPath, to retrieve a special folder's pathname or item ID list (PIDL).

If a special folder does not exist, you can force it to be created by using the following special CSIDL:

CSIDL_FLAG_CREATE
Version 5.0. Combine this CSIDL with any of the CSIDLs listed below to force the creation of the associated folder.

The remaining CSIDLs correspond to either file system or virtual folders. Where the CSIDL identifies a file system folder, a commonly used path is given as an example. Other paths may be used. Some CSIDLs can be mapped to an equivalent %VariableName% environment variable. CSIDLs are much more reliable, however, and should be used if at all possible.

CSIDL_ADMINTOOLS
Version 5.0. File system directory that is used to store administrative tools for an individual user. The Microsoft Management Console will save customized consoles to this directory and it will roam with the user.
CSIDL_ALTSTARTUP
File system directory that corresponds to the user's nonlocalized Startup program group.
CSIDL_APPDATA
Version 4.71. File system directory that serves as a common repository for application-specific data. A typical path is C:\Documents and Settings\username\Application Data. This CSIDL is supported by the redistributable ShFolder.dll for systems that do not have the Internet Explorer 4.0 integrated shell installed.
CSIDL_BITBUCKET
Virtual folder containing the objects in the user's Recycle Bin.
CSIDL_COMMON_ADMINTOOLS
Version 5.0. File system directory containing containing administrative tools for all users of the computer.
CSIDL_COMMON_ALTSTARTUP
File system directory that corresponds to the nonlocalized Startup program group for all users. Valid only for Windows NT® systems.
CSIDL_COMMON_APPDATA
Version 5.0. Application data for all users. A typical path is C:\Documents and Settings\All Users\Application Data.
CSIDL_COMMON_DESKTOPDIRECTORY
File system directory that contains files and folders that appear on the desktop for all users. A typical path is C:\Documents and Settings\All Users\Desktop. Valid only for Windows NT® systems.
CSIDL_COMMON_DOCUMENTS
File system directory that contains documents that are common to all users. A typical path is C:\Documents and Settings\All Users\Documents. Valid for Windows NT® systems and Windows 95 and Windows 98 systems with Shfolder.dll installed.
CSIDL_COMMON_FAVORITES
File system directory that serves as a common repository for all users' favorite items. Valid only for Windows NT® systems.
CSIDL_COMMON_PROGRAMS
File system directory that contains the directories for the common program groups that appear on the Start menu for all users. A typical path is C:\Documents and Settings\All Users\Start Menu\Programs. Valid only for Windows NT® systems.
CSIDL_COMMON_STARTMENU
File system directory that contains the programs and folders that appear on the Start menu for all users. A typical path is C:\Documents and Settings\All Users\Start Menu. Valid only for Windows NT® systems.
CSIDL_COMMON_STARTUP
File system directory that contains the programs that appear in the Startup folder for all users. A typical path is C:\Documents and Settings\All Users\Start Menu\Programs\Startup. Valid only for Windows NT® systems.
CSIDL_COMMON_TEMPLATES
File system directory that contains the templates that are available to all users. A typical path is C:\Documents and Settings\All Users\Templates. Valid only for Windows NT® systems.
CSIDL_CONTROLS
Virtual folder containing icons for the Control Panel applications.
CSIDL_COOKIES
File system directory that serves as a common repository for Internet cookies. A typical path is C:\Documents and Settings\username\Cookies.
CSIDL_DESKTOP
Windows Desktop—virtual folder that is the root of the namespace.
CSIDL_DESKTOPDIRECTORY
File system directory used to physically store file objects on the desktop (not to be confused with the desktop folder itself). A typical path is C:\Documents and Settings\username\Desktop
CSIDL_DRIVES
My Computer—virtual folder containing everything on the local computer: storage devices, printers, and Control Panel. The folder may also contain mapped network drives.
CSIDL_FAVORITES
File system directory that serves as a common repository for the user's favorite items. A typical path is C:\Documents and Settings\username\Favorites.
CSIDL_FONTS
Virtual folder containing fonts. A typical path is C:\WINNT\Fonts.
CSIDL_HISTORY
File system directory that serves as a common repository for Internet history items.
CSIDL_INTERNET
Virtual folder representing the Internet.
CSIDL_INTERNET_CACHE
File system directory that serves as a common repository for temporary Internet files. A typical path is C:\Documents and Settings\username\Temporary Internet Files.
CSIDL_LOCAL_APPDATA
Version 5.0. File system directory that serves as a data repository for local (non-roaming) applications. A typical path is C:\Documents and Settings\username\Local Settings\Application Data.
CSIDL_MYPICTURES
Version 5.0. My Pictures folder. A typical path is C:\Documents and Settings\username\My Documents\My Pictures.
CSIDL_NETHOOD
A file system folder containing the link objects that may exist in the My Network Places virtual folder. It is not the same as CSIDL_NETWORK, which represents the network namespace root. A typical path is C:\Documents and Settings\username\NetHood.
CSIDL_NETWORK
Network Neighborhood—virtual folder representing the root of the network namespace hierarchy.
CSIDL_PERSONAL
File system directory that serves as a common repository for documents. A typical path is C:\Documents and Settings\username\My Documents.
CSIDL_PRINTERS
Virtual folder containing installed printers.
CSIDL_PRINTHOOD
File system directory that contains the link objects that may exist in the Printers virtual folder. A typical path is C:\Documents and Settings\username\PrintHood.
CSIDL_PROFILE
Version 5.0. User's profile folder.
CSIDL_PROGRAM_FILES
Version 5.0. Program Files folder. A typical path is C:\Program Files.
CSIDL_PROGRAM_FILES_COMMON
Version 5.0. A folder for components that are shared across applications. A typical path is C:\Program Files\Common. Valid only for Windows NT® and Windows® 2000 systems.
CSIDL_PROGRAM_FILES_COMMONX86
Version 5.0. Program Files folder that is common to all users for x86 applications on RISC systems. A typical path is C:\Program Files (x86)\Common.
CSIDL_PROGRAM_FILESX86
Version 5.0. Program Files folder for x86 applications on RISC systems. Corresponds to the %PROGRAMFILES(X86)% environment variable. A typical path is C:\Program Files (x86).
CSIDL_PROGRAMS
File system directory that contains the user's program groups (which are also file system directories). A typical path is C:\Documents and Settings\username\Start Menu\Programs.
CSIDL_RECENT
File system directory that contains the user's most recently used documents. A typical path is C:\Documents and Settings\username\Recent. To create a shortcut in this folder, use SHAddToRecentDocs. In addition to creating the shortcut, this function updates the shell's list of recent documents and adds the shortcut to the Documents submenu of the Start menu.
CSIDL_SENDTO
File system directory that contains Send To menu items. A typical path is C:\Documents and Settings\username\SendTo.
CSIDL_STARTMENU
File system directory containing Start menu items. A typical path is C:\Documents and Settings\username\Start Menu.
CSIDL_STARTUP
File system directory that corresponds to the user's Startup program group. The system starts these programs whenever any user logs onto Windows NT® or starts Windows® 95. A typical path is C:\Documents and Settings\username\Start Menu\Programs\Startup.
CSIDL_SYSTEM
Version 5.0. System folder. A typical path is C:\WINNT\SYSTEM32.
CSIDL_SYSTEMX86
Version 5.0. System folder for x86 applications on RISC systems. A typical path is C:\WINNT\SYS32X86.
CSIDL_TEMPLATES
File system directory that serves as a common repository for document templates.
CSIDL_WINDOWS
Version 5.0. Windows directory or SYSROOT. This corresponds to the %windir% or %SYSTEMROOT% environment variables. A typical path is C:\WINNT.
2006/08/01 13:23 2006/08/01 13:23

맨 위로