2021년 신규 작성 

CryotoPP Example - cdeclog

 

CryotoPP Example

CryptoPP https://www.cryptopp.com/ Crypto++ 사용하기, 예제 암호화 지식 (개발자)

cdecl.github.io

 

--

C++ 용 암호화 라이브러리
 
Crypto++ 컴파일 
 
우선 해당 사이트에서 라이브러리를 다운 받은 후 원하는 컴파일러로 컴파일을 하여 dll 이나 lib 파일을 생성한다.
VC++ 2008 버전의 경우 프로젝트 파일이 따로 있지는 않고 VC++2005 버전을 업그레이드 후 컴파일 하면 됨
 
컴파일을 하면 cryptopp560\Win32 디렉토리에 각각 파일이 생성되고, dll 의 경우는 cryptopp560\Win32\DLL_Output 폴더에, static library 의 경우는 cryptopp560\Win32\Output 폴더에 각각의 모듈이 생성 된다. 
 
내가 테스트 할때는 dll 의 버전의 경우 이상하게 링크에러가 발생을 하여,
static library 를 사용하여 테스트를 하고 어플리케이션의 경우도 static library 로 컴파일을 해야 문제가 없었다.
 
블록 알고리즘 고려사항 
알고리즘 종류, 블록 알고리즘 운영 모드, 패딩종류, 인코딩 (텍스트 암호화의 경우)
 
알고리즘 SEED, AES, DES, 3-DES 설명 
 
 
DES
가장 오래되고, 세계적으로 가장 널리 사용되는 고전적 암호화 알고리즘이다. 파일이나 패킷을 암호화할 때 많이 사용된다. 하지만, 64비트 입력 블록과 56비트 짧은 비밀키를 사용하기 때문에, 더 이상 안전하지 않다고 간주하고 있다. 그러나, 국가 기밀을 다룰 정도로 극히 중요한 보안이 아니라면, 여전히 가장 널리 사용되는 알고리즘이다.
 
3-DES
DES를 3번 반복해서 암호화한다. 보안성이 향상되고, 그 만큼 성능은 떨어진다.
 
AES
미국 NIST에서 공모해서 표준화한 새로운 알고리즘이다. 128비트 입력 블록을 도입함으로써, 보안성을 향상했으며, 최근에 세계적으로 널리 사용되는 알고리즘이다.
 
SEED
KISA 주관으로 ETRI와 함께 국내에서 만들어진 알고리즘이다. 역시, 128비트 입력 블록을 사용하고 있고, 국제 표준에 부합하는 알고리즘이다.
 
 
 
 
블록 알고리즘 운영 모드 
 
ECB(Electronic codebook) : 평문을 일정 크기의 블록으로 나누어서 처리, 각 블록은 동일한 키로 암호
CBC(Cipher-block chaining) : 평문 블록과 바로 직전의 암호블록을 XOR한 것. 첫번째 암호 블록을 위해 초기 벡터 IV 값 사용
 
기타..
PCBC(Propagating cipher-block chaining)
CFB(Cipher feedback)
OFB(Output feedback)
CTR(Counter)
 
 
패딩(Padding) 종류
 
enum BlockPaddingScheme 
{NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
 
NO_PADDING : 패딩 없음
ZEROS_PADDING : NULL(0) 으로 패딩 
PKCS_PADDING : 패딩되는 바이트의 수의 같은 값으로 모두 패딩
ONE_AND_ZEROS_PADDING :  ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding
DEFAULT_PADDING : DEFAULT_PADDING means PKCS_PADDING 
  if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode), otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes)
 
 
예제, 필요한 헤더파일 (SEED, AES, DES 사용시..)
#include <iostream>
using namespace std;

//#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1   

// Crypto++ Includes
#include "cryptlib.h"
#include "Base64.h"
#include "aes.h"        
#include "seed.h"
#include "des.h"
#include "modes.h"      
#include "filters.h"    

#pragma comment(lib, "cryptlib")  

template <class TyMode>
std::string Encrypt(TyMode &Encryptor, const std::string &PlainText)
{
	std::string EncodedText;

	try {
		CryptoPP::StringSource(PlainText, true,
			new CryptoPP::StreamTransformationFilter(Encryptor,
				new CryptoPP::Base64Encoder(
					new CryptoPP::StringSink(EncodedText), false
					), CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
				)
			);
	}
	catch (...) {}

	return EncodedText;
}

template <class TyMode>
std::string Decrypt(TyMode &Decryptor, const std::string &EncodedText)
{
	std::string RecoveredText;

	try {
		CryptoPP::StringSource(EncodedText, true,
			new CryptoPP::Base64Decoder(
				new CryptoPP::StreamTransformationFilter(Decryptor,
					new CryptoPP::StringSink(RecoveredText),
					CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
					)
				)
			);
	}
	catch (...) {}

	return RecoveredText;
}

template <class Ty>
std::string CBC_Encrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string CBC_Decrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Decrypt(Decryptor, PlainText);
}

template <class Ty>
std::string ECB_Encrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string ECB_Decrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Decrypt(Decryptor, PlainText);
}


template <class CryptoType>
void Test()
{
	using namespace std;

	const std::string sText = "Plain Text";
	std::string sEnc, sDec;

	byte KEY[CryptoType::DEFAULT_KEYLENGTH] = { 0, };
	byte IV[CryptoType::BLOCKSIZE] = { 0x01, };

	// CBC 모드
	sEnc = CBC_Encrypt<CryptoType>(KEY, IV, sText);
	sDec = CBC_Decrypt<CryptoType>(KEY, IV, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "CBC_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;


	// ECB 모드
	sEnc = ECB_Encrypt<CryptoType>(KEY, sText);
	sDec = ECB_Decrypt<CryptoType>(KEY, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "ECB_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;
	cout << endl;
}


int main()
{
	using namespace std;

	// SEED 
	Test<CryptoPP::SEED>();

	// AES 
	Test<CryptoPP::AES>();

	// DES 
	Test<CryptoPP::DES>();

	return 0;
}
  
 

 


 패키지 활성화   JIT 활성화  멤버변수 상태 유지  전역변수 상태
 1. 서버 응용 프로그램  활성  유지 않함  유지 (활성화 개체 단위)
 2. 서버 응용 프로그램  비 활성  유지  유지 (활성화 개체 단위)
 3. 라이브러리 응용 프로그램  활성  유지 않함  유지 (세션 단위)
 4. 라이브러리 응용 프로그램  비 활성  유지  유지 (세션 단위)

* JIT 활성화가 있는경우 Method 단위로 m_spObjectContext->SetComplete() 를 호출 하여 테스트
* 풀링의 세팅의 경우 위의 결과와 틀리게 멤버변수의 상태가 달라 질 수 있음 
* CreateObject 이후 Nothing 까지의 상태 


내용 
- JIT 활성화인 경우 Method 단위로 클래스의 생성자 및 소멸자 호출 
- 풀링 설정의 경우 패키지가 시작할때 풀링된 구성요소 만큼 생성자를 호출하여 인스턴스 생성해 놓음 
- 라이브러리 응용 프로그램의 경우 인프로세스로 실행 되므로 전역변수값은 세션별로만 유지함
- regsvr32 로 등록되어 있는 컴포넌트랑 같은 효과를 내기 위해서는 "라이브러리 응용 프로그램, JIT 비활성화"로 운영

결론
내가 만들지 않은 컴포넌트의 경우 내부적으로 개체의 상태값 유지를 위해서,
멤버변수를 사용했는지, 지역 변수를 사용했는지 알 수 없기 때문에 regsvr32 로 등록하여 사용 하는것으로 권장

허나 COM+에 등록하여 사용 하려면 위의 내용 참고



'Dev > Windows' 카테고리의 다른 글

MS MTC 서비스 설정  (0) 2012.04.04
.svn 폴더 삭제  (0) 2011.03.25
Redmine 세팅  (0) 2009.09.12
ATL Com Project VC++ 6 에서 VC++ 8 변환(업그레이드)  (0) 2009.03.27
유니코드(UNICODE), C++  (0) 2008.10.16
BitNami Redmine Stack 받기: http://bitnami.org/stack/redmine


한글을 문제 없이 사용위해 DB를 UTF-8 로 설정 하기 위한 작업 + 기타 등등..

1. MySql 설정 변경 
-> \BitNami Redmine Stack\mysql\my.ini 

[client] 
default-character-set=utf8

[mysqld] 
character-set-client-handshake = FALSE 
init_connect=SET collation_connection = utf8_general_ci 
init_connect=SET NAMES utf8 
default-character-set=utf8 
character-set-server=utf8 
collation-server=utf8_general_ci

[mysql] 
default-character-set=utf8


2. MySql 설정 확인
-> \BitNami Redmine Stack\mysql\bin\mysql -uroot -p 

mysql> show variables like 'c%';
mysql> status;


3. 기존 bitnami_redmine DB, UTF-8로 다시 만들기 

mysql> drop database bitnami_redmine ;
mysql> CREATE DATABASE bitnami_redmine DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


4. 어플리케이션 DB 접속 encoding 수정 
-> \BitNami Redmine Stack\apps\redmine\config\database.yml

production:
  adapter: mysql
  database: redmine_production
  host: localhost
  username: bitnami
  password: bitnami 
  port: 3306
  encoding: utf8


5. 생성된 bitnami_redmine DB 설정 초기화 작업 

// 환경변수 세팅 
\BitNami Redmine Stack\scripts>setenv.bat
// DB Migration
\BitNami Redmine Stack\apps\redmine>rake db:migrate RAILS_ENV="production"


6. SMTP 설정 : 로컬 SMTP 서버 이용 
email.yml 수정 (기존 파일이 없을 경우 email.yml.example 를 복사후 rename)
->\BitNami Redmine Stack\apps\redmine\config\email.yml

production:
  delivery_method: :smtp
  smtp_settings:
    address: localhost
    port: 25
    domain:   
    authentication:
    user_name: 
    password: 
  

7. "일감" -> "이슈" 로 Replace (일감이란 단어의 어감이 좋지 않아서;;)
-> \BitNami Redmine Stack\apps\redmine\lang\ko.yml


출처 : 

- 기존에 TextWriter 객체에 Serialize 하니 XML Declaration 부분에 UTF-16으로 고정 되어서 MemoryStream 로 교체
- MemoryStream는 XML Declaration 부분을 표시 하지 않음


using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

// 구현
protected string SerializeToXML<T>(T t)
{
    string strXml = "";
    XmlSerializer xs = new XmlSerializer(typeof(T));

    try
    {
        using (MemoryStream ms = new MemoryStream())
        {
            xs.Serialize(ms, t);
            strXml = Encoding.UTF8.GetString(ms.ToArray());
        }

    }
    catch (Exception) { }

    return strXml;
}

'Dev > .NET' 카테고리의 다른 글

LUCENE.NET 검색엔진  (0) 2013.01.02
C# Web Service -> REST  (0) 2009.08.09
Integrating WCF Services with COM+  (0) 2008.09.03
Interop 응용 프로그램 배포  (0) 2007.10.05
RCW, CCW  (0) 2007.10.04
Web Service(WSDL), REST 어떤 방식으로 서비스를 만들면 좋을것인가 고민을 한적이있다.

그런데 왜 난 꼭 REST 방식을 웹페이지로 따로 만들어야 된다고 생각을 했을까?
그냥 아래와 같이 Web Service에 대해서 GET, POST 방식을 같이 노출하면 같이 사용할 수 있는데..


Web Service 의 인터페이스 메쏘드의 Input 파라미터에 대해서 Complex Type을 쓰지 않고 기본 타입을 쓰고,
web.config 에 아래와 같이 GET, POST 방식을 노출 해주면 끝.
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
하지만 Basic Type 을 쓰면 Strong한 타입 체킹을 할 수 없다는 단점이 있긴하다..

'Dev > .NET' 카테고리의 다른 글

LUCENE.NET 검색엔진  (0) 2013.01.02
SerializeToXML - C#  (0) 2009.08.10
Integrating WCF Services with COM+  (0) 2008.09.03
Interop 응용 프로그램 배포  (0) 2007.10.05
RCW, CCW  (0) 2007.10.04
C++0x RValue Reference 라는것이 추가 되었다.


RValue Reference는  Move semantics와 Perfect forwarding 이라는 두가지 기능을 가진다.


1. Move semantics

기존 부터 있던 Reference는 LValue Reference 라고 불린다.

int n = 10;
int &r = n;  // LValue Reference
int *p = &n;  // 포인터 참조 방식
cout << r << " " << *p << endl;

C++의 참조는 내부적으로 포인터를 사용하여 참조를 하게 되지만 사용함에 있어 보다 우아하게(?) 사용을 할 수 있다는 장점이 있다.


반면 RValue Reference는 아래와 같이 사용한다.

int n = 10;
int &&r =n; // 그런데 기존 참조랑 머가 틀리냐??

int, long 등의 기본 타입과 기존 클래스의 복사생성자, 대입연산자에 대해서는 RValue Reference 참조는 기존 Value Reference와 똑같이 동작을 한다.

하지만 RValue Reference는 객체(변수)의 주소를 참조하는 기존의 LValue Reference와 틀리게,
RValue Reference 로 겹지정한 복사생성자 및 대입연산자를 따로 구현, 그리고 그것을 의도적으로 호출하게 할 수 있다.

그리고 그 RValue Reference 로 겹지정한 복사생성자 및 대입연산자에는,
임시객체애 대해서 복사가 아닌  메모리를 이동 (Move) 하는 방법으로 임시 객체의 생성및 소멸에 대한 비용을 줄이는 구현이가능해 진것이다.

소유권 이전 기법을 사용하는 auto_ptr 처럼..



class Item
{
  public:
    Item() : p(new char[100]) {}
    Item(const Item &t) : p(new char[100]) {  memcpy(p, t.p);  } // 복사생성자
    Item(Item &&t) : p(t.p) { t.p = NULL;  } // Move 생성자

    // Item& operator=(const Item &t) { return *this; } // 대입연산자
    // Item& operator=(Item &&t) { return *this; } // Move 대입 연산자
    // ...
   ~Item() { if (p) delete p; }
  
  private:
    char *p;
};

Item&& foo()
{
  Item item;
  // ...
  return item;
}

int main()
{
  Item item;
  Item t = item; // 복사생성자 호출
  Item &r = item; // 참조

  Item &&rr = Item; // 참조
  Item &&mv = std::move(item);  // Move 생성자
  Item &&mvt = foo(); // // Move 생성자
}

위의 코드와 같이 foo() 함수에서 RValue Reference로 리턴을 하게 되면,
Item 객체의 RValue Reference 버전의 Move 생성자가 호출되고
Move 생성자에서 내부 멤버인 포인터의 소유권을 이전하여 임시객체에 대해서 필요 없는 생성-소멸의 과정을 거치지 않게끔 할 수 있는것이다.

그리고 강제로 Move 생성자, Move 대입 연산자를 호출 하기 위해서 std::move() 함수를  이용 할 수도 있다.


C++0x 의 STL에는 RValue Reference 의 코드가 적용 되어 있어 사용하는 것 만으로도 성능 효과를 볼 수가 있다고 한다.
대략 다음과 같은 코드..

std::string s = "s";
std::string str;
str = s + "t" + "r" + "i" + "g";  // 임시객체 (RValue Reference) 사용



2. Perfect forwarding

template 의 내부 함수가 참조 및 상수의 값을 파라미터로 받을 경우 관련되서 여러 개의 버전 구현을 해야하는 문제를,
RValue Reference의 문법으로 하나로 처리 하는 내용.
(자세한 내용은 아래링크 -_-; )



참고 : http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx


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

boost::asio 클라이언트 소켓 (timeout 기능)  (0) 2010.10.14
이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x Lambda  (0) 2009.05.20
C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
아래 링크의 글 중 Herb Sutter 의 Lambda 예제 및 설명에 관한 리플..
http://herbsutter.wordpress.com/2008/03/29/trip-report-februarymarch-2008-iso-c-standards-meeting/

[]와 []안에 들어가는 내용에 대해서 명쾌하게 설명을..




Herb Sutter

Re binders: Okay, I give! I’ll use a better example next time.

(no name) asked: "How are local variables captured?" You have to specify whether it’s by copy or by reference. So this example is illegal because it tries to use a local variable:

    int numWidgets = 0;
    for_each( v.begin(), v.end(), []( Widget& w )
    {
        ++numWidgets;  // error, numWidgets is not in scope
    } );

If you want to update numWidgets directly, capture it by reference:

    for_each( v.begin(), v.end(), [&numWidgets]( Widget& w )
    {
        ++numWidgets;  // increments original numWidgets
    } );
    // numWidgets == v.size() here

Or use the shorthand [&] to take all captured variables implicitly by reference:

    for_each( v.begin(), v.end(), [&]( Widget& w )
    {
        ++numWidgets;  // increments original numWidgets
    } );
    // numWidgets == v.size() here

What if you want a local copy? You say to pass it by value, but for safety reasons the current proposal says you get a read-only copy that you can’t modify:

    for_each( v.begin(), v.end(), [numWidgets]( Widget& w )
    {
        int i = numWidgets; // ok
        ++i;
        // "++numWidgets;" would be an error
    } );
    // numWidgets == 0 here

Or use the shorthand [=] to take all captured variables implicitly by copy:

    for_each( v.begin(), v.end(), [=]( Widget& w )
    {
        int i = numWidgets; // ok
        ++i;
        // "++numWidgets;" would be an error
    } );
    // numWidgets == 0 here

Similarly, for the question: "What will happen in the following case:"

    int flag = 0;
    mypool.run( [] { flag = 1; } );
    cout << flag << endl;

The answer is that the code is illegal, you have to say whether you capture flag by value or by reference, which can be as simple as replacing [] with [=] or [&]. And if you capture by value, you get a read-only copy so you couldn’t assign to it.


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

이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x, RValue Reference  (0) 2009.05.27
C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29

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

C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29
asio C++ library  (0) 2008.08.22
기 작성되어 있던 C++ 컴포넌트에서 한개의 함수에 너무 많은 코드로 인해,
컴파일러 내부 오류를 경험하고 해당 코드에 대해서 리팩토링을 결심!!

관련된 작업은 Extract Method 이며 자동으로 해당 부분을 추출하여 Method를 만들어 주는 툴을 중심으로 알아 보았다.

이것 저것 알아보던 중 2개의 후보가 눈에 띠었다.
대상은 "Refactor! For Visual C++ 2005"와 "Visual Assist X" 에서 지원하는 Refactoring 에 관련된 기능이다.

결론부터 얘기하면 "Refactor! For Visual C++ 2005"의 기능이 쓸만 하였고 Visual Assist X 의 리팩토링 기능은 간단한 기능을 제외하고는 그다지 유용하지 못하였다.


Visual Assist X
Visual Assist X 는 Visual Studio 에서 코딩에 도움을 주는 유용한 기능이 있는 Add-in 툴로서 최신 버전에는 리팩토링 기능까지 추가가 되었다.

예상했던 대로 속도는 무난히 빨랐으며 간단한 목적으로 사용하기에는 문제가 없으나 몇가지 사항에 대해서는 조심히 사용 해야 될듯하다.

1. Extract Method 의 경우 10개 까지의 파라미터 까지 밖에 지원 하지 않는다.
  - Extract Method의 대상 코드의 파라미터의 지원이 10개까지 밖에 지원하지 않는다
  - 나머지에 대해서는 수작업 신공..

2. Extract Method 의 구문 중 return 이 포함되어 있는 구문에 대해서 별 다른 코드를 넣어주지 않는다.
  - 이것도 나머지는 수작업 신공 -_-;

// 원본코드
bool Run()
{
    int a = 0;
    if (a == -1) {
        return false;
    }

    cout << "next process " << endl;

    a = 10;
    return true;
}

// Extrace Method 후의 코드
bool MyMethod( int a )
{
    if (a == -1) {
        return false;
    }

    cout << "next process " << endl;
}



bool Run()
{
    int a = 0;
    return MyMethod(a);

    a = 10;
    return true;
}


3. Rename 의 경우 바꾸지 못하는 경우 발생
  - 특수한 경우에 구문 분석으로 발견하지 못하여 변경을 못해주는 경우 발생

4. VC++6, VC++2005 버전등 여러 버전 사용 가능
  - 단 VC++6 의 경우 코드 "실행 취소"로 되 돌릴 경우 리팩토링 액션 단위가 아닌 한줄 한줄의 단위로 되 돌리기가 된다.
  - 머 이것도 VC++6 을 안쓰면 되지 머..




Refactor! For Visual C++ 2005

1. 모든 기능적인 부분에서 합격점이지만 속도가 많이 느린 경우 발생
  - 특히 많은 코드에 대해서 리팩토링의 경우 IDE가 뻣었나! 라는 생각이 들 정도로 행이 걸려 있는 상태가 지속
  - 아마도 아래와 같은 UI 부분의 지원 때문에 느리지 않나 생각이 들며 IDE를 처음 로딩할때도 DxCore 라는 모듈을 로딩할때 시간이 좀 걸린다.

refactor1.jpg



2. Visual Assist X 에서 문제였던 코드 중간의 return 부분을 별도의 return 여부를 판단하는 파라미터를 이용하여 처리 해주고 있다.

// 원본코드
bool Run()
{
    int a = 0;
    if (a == -1) {
        return false;
    }

    cout << "next process " << endl;

    a = 10;
    return true;
}


bool RunExtracted(int a, bool &pShouldReturn)
{
    pShouldReturn = false;
    if (a == -1) {
        pShouldReturn = true;
        return false;
    }

    cout << "next process " << endl;
    return false;
}

bool Run()
{
    int a = 0;
    bool lShouldReturn;
    bool lResult = RunExtracted(a, lShouldReturn);
    if (lShouldReturn)
        return lResult;

    a = 10;
    return true;
}


3. Rename 등의 작업을 할때 링크 라는 개념의 함수의 정의, 구현, 호출 부분을 연결된 데이터를 관리하며 UI도 비슷하게 동작을 하는것 같다
  - 허나 UI때문인지 속도 부분에서도 약간 더딘 면이 없지 않아 있다.


4. 무엇보다도 장점인 무료.. 허나 현재는 VC++ 2005만 무난히 적용 되는 것으로 보이며, 
추후에는 더 발전 되어있는 모습으로 더욱 쓸만한 툴이 되지 않을까 생각한다.



결론.

위의 두개의 툴은 그 외에도 많은 리팩토링 기법의 도구를 제공을 하며,
C++의 문법 복잡성에 의해 다른 언어에 비해서 많이 더뎠던 리팩토링 자동화 부분에서 어느정도 해소가 되지 않았나 생각이 든다.

아  이제 C++에서도 리팩토링을 툴로 제공을 하는구나... 흐흐..

앞으로 좀 더 발전을 하면 VC++ 에서도 C#처럼 내장 IDE에서 리팩토링을 제공을 하는 날이 있지 않을까 생각을 한다.



이상 허접한 리팩토링 툴 비교기..

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

C++0x Lambda  (0) 2009.05.20
C++0x 지원 컴파일러 목록  (0) 2009.05.20
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29
asio C++ library  (0) 2008.08.22
C++ 0x - Herb Sutter의 블로그 글  (0) 2008.07.29
VC++ 6 에서 ATL Com Project 만들어진 프로젝트를 VC++ 8 로 업그레이드를 할 경우 몇가지의 문제가 발견 되었다.


1. LINK : fatal error LNK1104: 'mtxguid.lib' 파일을 열 수 없습니다.

확인 해보니 더 이상 VC++ 8 버전에서는 'mtxguid.lib'가 존재 하지 않는다.
다른 lib 로 바이너리들이 통합 된것으로 보이며 링커 옵션에 추가 되어 있는 'mtxguid.lib' 를 지우면 된다.

추가적으로 main을 못찾는다는 링크 에러가 발생하면 "ATL에서 CRT 사용 최소화" 옵션을 사용 하지 않는다.


2. GetObjectContext 링크 에러

링크 옵션에 "comsvcs.lib" 를 추가 하면 된다.



3. def 파일의 심볼에 서수 지정 경고

아래와 같이 def 파일의 함수 이름에 서수가 지정 되어 있으면 아래와 같이 경고가 표시 된다
warning LNK4222: 내보낸 'DllCanUnloadNow' 기호를 서수로 지정하면 안 됩니다.
warning LNK4222: 내보낸 'DllGetClassObject' 기호를 서수로 지정하면 안 됩니다.
warning LNK4222: 내보낸 'DllRegisterServer' 기호를 서수로 지정하면 안 됩니다.
warning LNK4222: 내보낸 'DllUnregisterServer' 기호를 서수로 지정하면 안 됩니다


그런 경우 def 파일을 열어서 아래와 같이 서수에 해당하는 부분을 지워 준다.
EXPORTS
    DllCanUnloadNow     PRIVATE
    DllGetClassObject   PRIVATE
    DllRegisterServer   PRIVATE
    DllUnregisterServer    PRIVATE


그 외에 deprecation 되어 있는 CRT 함수들의 경고들은 무시해 주거나 새로운 버전의 CRT 함수를 사용 하면 된다.

ex) sprintf -> sprintf_s



참고 : http://social.microsoft.com/Forums/en-US/vcgeneral/thread/1b44c27b-db1c-4879-9eb9-4bf2a128b88f

'Dev > Windows' 카테고리의 다른 글

COM+ 패키지 활성화별 세션 상태 정리  (0) 2009.09.22
Redmine 세팅  (0) 2009.09.12
유니코드(UNICODE), C++  (0) 2008.10.16
VARIANT 에서 객체 추출하기  (0) 2008.09.09
ffmpeg  (0) 2008.04.09




C++ 0x에 대한 리뷰 동영상인가 보다.

시간있을때 하나씩 정리를 해볼까 하는데.. 움..

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

C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
asio C++ library  (0) 2008.08.22
C++ 0x - Herb Sutter의 블로그 글  (0) 2008.07.29
C++ 0x  (0) 2008.05.09
유니코드 (네이버 백과사전)
국제표준으로 제정된 2바이트계의 만국 공통의 국제 문자부호 체계(UCS: Universal Code System)를 말한다. 애플컴퓨터·IBM·마이크로소프트 등이 컨소시엄으로 설립한 유니코드(Unicode)가 1990년에 첫 버전을 발표하였고, ISO/IEC JTC1에서 1995년 9월 국제표준으로 제정하였다. 공식 명칭은ISO/IEC 10646-1(Universal Multiple-Octet Coded Character Set)이다.

유니코드는 전세계 문자코드를 정의하기 위해서 만든 놈이다

그럼 이전에는 어떻게 표현 했는가?

이전에는 알파벳틱한 애들은 1바이트에서 7비트 내로 표현하고(Ascii) 그외에 확장적인 문자가 코드 127 위로 표시되고, 한글과 같이 더 많은 바이트가 필요한 것들은 2바이트로 표현을 했다.

그래서 문제는 코드 127 위로 넘어가면 윈도우의 경우 각 나라의 OS별로 표현하는 방법이 틀렸다
(이전에 터보C 3.0 이전 IDE를 생각하면 될것이다. 콘솔화면으로 표현한 UI에서 옆에 테두리가 어떻게 나왔는지를...)

한글의 경우도 2바이트 문자로 표현을 하였고 이것을 MBCS(Multibyte Character Set) 이라고 한다.



UNICODE 

2바이트 문자를 표현하기 위해 만든 C++의 타입이 있었으니 그것이 바로 wchar_t 타입이다.
(그런데 wchar_t 의 경우 OS마다, 컴파일러마다 정의가 약간 틀린듯하다. -_-;; )

그럼 문자열을 어떻게 표현을 할까?
정수를 long 타입으로 표현할때 쓰는 뒤에 L를 붙이는것과 일맥상통 하게 앞에 L 을 붙여서 표현한다.

10 (int)
10L (long)

"a" (char)
L"a" (wchar_t)

wchar_t wsz[] = L"김";   // UNICODE 총 2바이트 사용 (2바이트 문자셋 1개 사용)
char sz[] = "김";            // MBCS 총 2바이트 사용 (1바이트 문자셋 2개 사용)


그리고 wchar_t 타입에 대응되는 표준 라이브러리들이 아래와 같은 놈들이다.
C++ 클래스 : wostream, wfstream, wstring ...
C 함수 : wcslen, wcslen ...

그리고 WinAPI 로는...
MessageBoxW, GetCurrentDirectoryW, CreateDirectoryW

어라.. 근데 처음 보는 놈들일것이다.
MessageBox 는 알아도 MessageBoxW 는 무엇인가...
MSDN 를 뒤져도 찾기가 쉽지 않다.

WinAPI 에서는 문자열을 사용하는 API에 대해서 MBCS와 UNICODE에 대응되는 함수를 각각 가지고 있다.
그리고 거의 모든 API 에서 뒤에는 A(MBCS) 또는 W(UNICODE) 를 붙이는 것으로 표시를 하고 있는것이다.

그래서 MessageBox 라는 것은 함수 이름이 아니며 그것들을 스위칭 하는 매크로 이름이다.
실제 함수는 아래와 같이 MessageBoxA 혹은 MessageBoxW 로 매크로에 의해 치환되는것이다.

#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE


관련해서 타입들도 이런한 것들이 존재한다.

LPCSTR =>  const char *
LPCWSTR =>  const wchar_t *
LPCTSTR =>  LPCSTR <-> LPCWSTR 스위칭 

"김" =>  const char *
L"김" =>  const wchar_t *
_T("김") =>  "김" <-> L"김" 스위칭

이 스위칭들은 UNICODE 와 _UNICODE 매크로 정의에 의해서 각각 해당 함수 혹은 타입으로 정의가 된다.
(UNICODE 와 _UNICODE 을 두개를 같이 정의 해야되는데 왜 2개를 만들었는지 모르겠다. 암튼..)

그리고 MSDN에서는 아래와 같이 함수인양 사기(?)를 치는것이다.

MessageBox
The MessageBox function creates, displays, and operates a message box. The message box contains an application-defined message and title, plus any combination of predefined icons and push buttons.

int MessageBox(
  HWND hWnd,          // handle of owner window
  LPCTSTR lpText,     // address of text in message box
  LPCTSTR lpCaption,  // address of title of message box
  UINT uType          // style of message box
);



UTF-8, UTF-16 ??

위에서 얘기했듯이 일반적으로 유니코드는 2바이트 문자로 표현을 한다.
그러다 보니 한글 파일의 경우 MBCS나 UNICODE나 크기가 별반 차이가 없다.

그런데 영어권 애들의 파일을 보자..
게네들은 겉으로는 아무것도 낳아진것이 없는데 파일의 크기가 2배가 되어야 한다.
이런 어처구니 없는 경우가 있나..
(내가 생각해도 그렇다. 허나 뒤에가면 우리가 어처구니 없어진다. ㅎㅎ)

그래서 얘네들이 머리를 굴려서 유니코드를 표현하는 방식을 여려게 만들었다.
그것이 바로 UTF (Unicode Transformation Format) 이다.

그중에 일반적으로 유니코드라로 불리는 2바이트 체계 표현이 UTF-16 이고,
영어권은 1바이트 기타 언어는 4바이트까지 가변적으로 표현 가능한것이 UTF-8 이다.
(유니코드의 127 까지의 문자는 ASCII 문자코드와 동일하다. 그래서 영어권 1바이트가 ASCII와 호환이 되는것이다.)

http://ko.wikipedia.org/wiki/UTF-16
http://ko.wikipedia.org/wiki/UTF-8

이러다 보니 한글은 UTF-8 로 가면 4바이트로 표현이 되어 버린다. 


UTF-8 

그럼 UTF-8 은 어떤 타입을 써야 하는가? 
char [] 아니면 wchar_t [] ??

아직까지 표준으로 정해진것은 없는 것으로 안다.
차기 표준에서 이것에 대해서 논의가 되고 있으니 좋은 결과가 있을것으로...


Byte Order Mark

2바이트 혹은 그 이상의 바이트로 표현을 하다보니 정수표현과 같이 머신, 플랫폼 간의 바이트 오더링(little-endian, big-endian)의 문제가 있다.


유니코드 파일

윈도우 유니코드 파일의 경우 아래와 같은 문자를 파일 맨앞에 세팅함으로서 구분을 한다
(이게 표준인지 윈도우만 그런지는 잘 모르겠다...)

유니코드(UTF-16, little-endian) : 0xFF 0xFE
유니코드 big endian (UTF-16, big-endian) : 0xFE 0xFF
UTF-8 : 0xFE 0xFF

'Dev > Windows' 카테고리의 다른 글

Redmine 세팅  (0) 2009.09.12
ATL Com Project VC++ 6 에서 VC++ 8 변환(업그레이드)  (0) 2009.03.27
VARIANT 에서 객체 추출하기  (0) 2008.09.09
ffmpeg  (0) 2008.04.09
벤치마킹  (0) 2007.10.17

+ Recent posts