블로그 이미지
fiadot_old

칼퇴근을 위한 게임 서버 개발 방법론에 대한 심도있는 고찰 및 성찰을 위한 블로그!

Rss feed Tistory
Diary 2008. 1. 2. 07:01

신년 목표 설정...

작년 초에 세웠던 목표는 논문, 대학원관련 부분만 제외한다면 거의 대부분 목표를 이뤘다.

제일 큰게 빠진거 같긴 하지만...


[2008년 할일]

- 잉사마
  1. 잘지내기~ 잘지내기~ 잘지내기 ^^

- 대학 관련 
  1. 봉사활동 40시간
  2. 정보처리 기사
  3. 4학년 평점 올리기
  4. 2학기 학비 모으기

- 대학원 관련
  1. 토익(850), 영어면접 준비
  2. 학교/랩실 알아보기 (풀타임/파트타임)
  3. 전공 이론 공부(자료구조, OS, 네트워크 중심)
  4. DSP관련 논문작성(한,영)

- 개인 / 업무
  1. 마소 매달 원고 작성 (네트워크와 메타프로그래밍 위주)
  2. 프로젝트 서비스까지 무사히 -_-;;    
  3. 연봉 올리기
  4. Distortion VST 제작
  5. 기타 다시 잡기


항상 생각하고 있던거지만 다시한번 정리하는 마음에서 적어본다.

시간이 부족하다는건 시간 활용을 잘못하기 때문이고,

미련이 남는다는건 최선을 다하지 않았다는 거...

안되면 내년에 더 공부하면되지머 ㅋㅋ

,
Technical Article 2007. 12. 27. 03:03

SP Dispatcher에 대해...

어느 정도 네트웍 엔진의 골격을 잡고 최근 DB프로그래밍쪽에 많은 시간을 할애하고 있다.

Cache DB로 완전한 전환을 하기 전에 구현된 SP(Stored Procedure)들에 대해 스키마를 얻어오고 그 정보를 토대로 ATL Consumer Wizard의 Accessor 생성기와 유사한 형태의 코드 제네레이터를 만들었다.

sp이름을 통해 parameter와 column의 타입, 이름, 길이를 얻어서 생성하고 맵핑까지 끝냈는데... 앗싸 좋쿠나 하고 있던 찰라 문제가 발생했다.
 
insert와 update에 대해서 까지 미쳐 생각이 닿지 못했다.

PK가 먹어 있는 테이블에 insert를 더미값으로 집어넣으니 integratviloation이 뜰수밖에 ㅡ_ㅡ;


초기에 생각했던 sp구조 데이터를 토대로 boost::spirit을 이용해서 파싱해서 생성하는 방법으로 돌아가게됐다. 대신에 기존의 DBA가 작업하던 엑셀 시트에서 약간의 변형된 형태로 사용하는 구조로 번거로움을 줄이면서 작업하는 방향으로 합의를 봤다..


지금 시간 새벽 3시 ...

4시까지 하면 다 할수 있을꺼 같은데 ...^^;
,
Technical Article 2007. 11. 19. 09:16

Visual Studio Project에서 VSS(소스 세이프) 제거하기

[노가다 방법]

1. 읽기전용 속성 제거
2.  *.scc 파일과 *.vssscc 파일, *.vspscc 파일을 제거
3. sln 파일을 텍스트에디터로 불러
GlobalSection(SourceCodeControl) = preSolution
..
EndGlobalSection  (첫번째 나오는..)
까지 지운다

4. vcproj 파일을 텍스트에디터로 불러
SccProjectName="SAK"
SccAuxPath="SAK"
SccLocalPath="SAK"
SccProvider="MSSCCI:Microsoft Visual SourceSafe"
이 부분을 지운다


[쉬운방법]

사용자 삽입 이미지





툴바에 "소스제어"를 추가하면 소스제어 변경 아이콘(제일 앞에 선택된거)이 보인다.

클릭하면 솔루션, 프로젝트 별로 바인딩상태가 보이는데, 바인딩/해제 를 할수있다.

-_- 노가다 즐~

,
마이크로소프트웨어 2007. 10. 9. 11:13

OLEDB를 이용한 MICROSOFT OFFICE EXCEL2007 데이터 읽기

[마소플러스]  2007년 12월 기고
분류 Windows Technic – OLEDB

OLEDB를 이용한 Microsoft Office Excel2007 데이터 읽기

서론

Excel의 데이터를 사용해야 할 경우 다양한 방법이 있다. 예를 들어, 텍스트파일이나 CSV로 추출해서 파싱해서 사용하는 방법, 스키마 맵핑을 통해 XML로 추출하는 방법, 직접 접근하는 방법등을 들 수 있다.

OLEDB ATL을 이용하여 보다 빠르고 쉽게 자신의 프로그램에 Excel의 데이터를 사용하는 방법에 대해서 알아보자.

 

Excel 2007을 위한 Provider의 등장

과거 바이너리 파일 포맷이던 Microsoft Office Excel의 데이터 파일 포맷은 Microsoft Jet OLE DB Provider를 이용해서 접근이 가능했다. 하지만 Microsoft Office 2007이 출시되면서 Open Office XML(OOXML)이라는 XML기반 포맷으로 변경되었다. 이에 새로운 Provider를 제공하는데

Microsoft Office 12.0 Access Database Engine OLE DB Provider이다.

<.xls에 접근하는 Connection String>

Provider=Microsoft.Jet.OLEDB.4.0; Data Source=excelfilename.xls;

Mode=Read;Extended Properties=”Excel 8.0;HDR=YES”; Persist Security Info=False

 

<.xlsx에 접근하는 Connection String>

Provider=Microsoft.ACE.OLEDB.12.0; Data Source=excelfilename.xls;

Mode=Read;Extended Properties=”Excel 12.0;HDR=YES”; Persist Security Info=False

* HDR=YES 일때 첫번째 열이 컬럼 이름이 된다.

 

<샘플 엑셀 데이터>

 

 

샘플 프로젝트

Visual Studio 2005를 기준으로 설명하도록 한다.

1.     프로젝트를 생성한 뒤 클래스 추가-ATL-ATL OLEDB 소비자 를 선택한다

2.     데이터 소스를 선택하여 공급자 탭에서 Microsoft Office 12.0 Access Database Engine OLE DB Provider를 선택한다.

                     <그림 1>

3.     연결탭에서 데이터 원본에 xlsx파일 경로를 지정해준다.

4.     고급탭에서 엑세스권한을 ReadWrite를 체크한한다.

5.     모두탭에서 Extended Properties의 속성 값을 Excel 12.0;HDR=YES 를 입력한다

6.     연결탭으로 돌아와 연결 테스트를 해본다. “연결 테스트를 성공했습니다.” 가 나오면 정상적으로 접근이 가능한 상태이다. (에러가 발생한다면 엑세스권한과 파일경로를 확인해보면 된다.)

7.     확인을 누르면 테이블에 Work Sheet가 쭉 나열되는데 샘플로 제작했던 NameCard$를 선택한 후 확인을 누른다.

          <그림 2>

Wizard를 통해 생성된 NameCard WorkSheet에 해당하는 Accessor의 코드가 생성되어

NameCard.h 의 소스가 보일 것이다.

Connection String에 비밀번호가 있을 수도 있기 때문에 컴파일시에 확인하라는 의미로 #error가 되어있는데 이 부분을 주석 처리한다.

// #error Security Issue: The connection string may contain a password

 

그럼 Excel2007의 데이터를 읽어보도록 한다.

 

#include <iostream>

#include "NameCard.h"

using namespace std;

 

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

{

        setlocale(LC_ALL, ".949"); // 한글 코드페이지

        CoInitialize(NULL);    // OLE DB 를 위한 COM초기화

 

        CNameCard rs; 

        rs.OpenAll();

 

        HRESULT hr;

        while ( SUCCEEDED(hr = rs.MoveNext()) )

        {

               if ( DB_S_ENDOFROWSET == hr ) // 레코드셋 끝일 때

                       break;

 

               wprintf(L"Age=%f Name=%s \n",  rs.m_Age, rs.m_Name);

        }

        rs.CloseAll();

 

        CoUninitialize();

        return 0;

}

 

 

이제 자동 생성된 코드에서 중요한 부분은 ATL Consumer 코드부분을 살펴보도록 하겠다.

class CNameCard : public CCommand<CAccessor<CNameCardAccessor> >

여기서  CAccessor는 데이터 베이스의 구조를 알고 있는 경우 결과 데이터셋에 대한 바인딩 방식을 지정하는 방법중의 하나이다. 동적여부와 매개변수등에 대한 정보에 따라서 사용해야 할 Accessor의 종류가 다르다.

우리는 age name이라는 2개의 필드 구조라는 것을 알고 있으므로 CAccessor를 사용한다.

그리고 CCommand부분은 명령(SQL)를 통해서 rowset에 접근할 수 있음을 의미하는데,

자동 생성된 코드에서 이 부분이 기본 명령에 해당한다.

DEFINE_COMMAND_EX(CNameCardAccessor, L" \

        SELECT \

               Age, \

               Name \

               FROM `NameCard$`")

 

 

결론

OLEDB Consumer Wizard를 통해 Excel데이터에 맞게 Accessor Command의 코드를 생성해줌으로 개발자의 편의를 도모할수 있다. 또한 그림2의 지원부분 변경,삽입,삭제에 체크를 하고, 쿼리를 수정하면, 단순히 데이터를 읽어오는 것 뿐만 아니라 Insert, Update, Delete등의 모든 기능을 사용할수 있다.

 

참고자료

OLE DB Connection Manager

http://technet.microsoft.com/en-us/library/ms141013.aspx

 

How to: Loop through Excel Files and Tables

http://technet.microsoft.com/en-us/library/ms345182.aspx [E]

http://technet.microsoft.com/ko-kr/library/ms189667.aspx [K]

 

데이터 연결 마법사를 사용하여 Office Publisher, Visio 또는 Word로 데이터 가져오기

http://office.microsoft.com/ko-kr/word/HA102090051042.aspx

 

데이터 액세스 기술

http://msdn.microsoft.com/library/kor/default.asp?url=/library/KOR/vsent7/html/dvconChoosingRightDataAccessTechnology.asp

 

OLE DB 프로그래밍

http://msdn.microsoft.com/library/kor/default.asp?url=/library/KOR/vccore/html/vcconOLEDBProgramming.asp




 

Word File Download


,
Technical Article 2007. 9. 28. 22:58

OLEDB의 Connection Pool에 대한 기본값 사용시 4가지 방법에 대한 수행속도 비교

MSSQL2K와 OLEDB Provider를 사용하여 VS6기반 ATL을 사용하여

OLEDB Wrapper를 구성해서 게임용 DB서버에서 사용하고 있었다.


올 중순부터  VS2005로 넘어오고 MSSQL2005로 바꾸면서,

기존의 네트워크 모듈부분을 뜯어고치면서

부분적으로 COM으로 구성하던 중,

DB쪽을 손보면서 OLEDB Wrapper에 대해 코드 리뷰를 하게 되었다.


기존 구조에서는 DBMS와의 연결은 단일하게 하고

Session을 DataSource에서 얻어와서 Accessor에서 사용하는 방식이였다.

즉, Stored Procedure나 query가 호출될때 session을 새로 생성하는 방식이다.

당시에는 MSSQL2K에서 Connection Pooling을 기본적으로 지원하기 때문에

Connection에 대해 크게 신경을 안쓰고 작성 했었는데, 이부분이 살짝 걸리긴 했다.

다른 방식에 대해서 성능 테스트를 해보지 못하고,

시간에 쫒겨서 만들었기 때문에  한번 검증해 보고자 테스트 코드를 만들어봤다.



환경은 Windows XP+SP2, MSSQL2005+SP1,

VS2005+SP1, MS OLEDB Provier for SQL Server 이다.

Connection스트링에 대한 옵션은 default값으로 하였다.

4가지 경우에 대한 성능 테스트를 진행해보았다.

공통적인 부분은 스레드 2개를 통해 SP(Stored Procedure)를 호출하는 consumer를 통해

recordset을 fetch하는 부분이다.

* TACCSSOR는 CCommand<CAccessor<CS_SP명> >을 상속한 클래스 인스턴스

 Case1>  Wizard를 통해 생성된 ATL OLEDB 소비자(consumer)를 그대로 사용 했다.
 ThreadFunc1()
 {
  TACCSSOR.OpenAll();  
 ...read...
 TACCSSOR.CloseDataSource();
 }

 Case2> DataSource 연결 1개. DataSource를 통해 Session 연결 1개.
 ThreadFunc2()
 {
 TACCESSOR.Open(미리 생성해둔 Session전달);
 ...read...
 TACCESSOR.Close();
}

 Case3> DataSource 연결 1개.  세션은 매번 생성
 ThreadFunc3()
 {
 CSession  session;
 _session.Open(DataSource); // DataSource를 인자로  Session생성
 TACCESSOR.Open(미리 생성해둔 Session전달);
 ...read...
 TACCESSOR.Close();
}

Case4> DataSource 연결1개, 자체 세션 풀 구성
ThreadFunc4()
{
CSession *pSession = GetSession();
 TACCESSOR.Open(*pSession);
 ...read...
 TACCESSOR.Close();
FreeSession(pSession);
}

즉, 기존에 구성했던 방식은 Case2에 해당된다.

과연 어떤 결과가 나올것인가?? 하하하~ 흥분 흥분 *--*;;

각각의 케이스에 대해 ThreadFunX를 1000회씩 실행한 결과이다.


const int DBPOOL_CASE = 1;   // 9567, 9511, 9560
const int DBPOOL_CASE = 2;   // 4388, 4402, 4375
const int DBPOOL_CASE = 3;   // 1162, 971, 977
const int DBPOOL_CASE = 4;   // 470, 530, 468

왜 이런 결과가 나온것일까??

Case1의 기본으로 생성해주는 consumer코드는 매번 DataSource를 연결하지만

Connection Pool이 구성되어 있다면 Case 2와 크게 차이가 없어야 맞다.

하지만, OpenAll 메소드 안에서 Propertie들에 대해 셋팅하는 부분과 OpenRowset을 호출하는

몇단계의 함수콜이 더 들어가게 된다. 이부분에서 시간을 소요하게 되는것이다.

Case2가 Case3보다 느린이유는 DataSource와 Session을 단일하게 사용하게 되면서

Bottle neck이 발생했다고 보는게 맞다.

(추가적으로 얻을수 있는 정보는 Session이 하나라도 자동적으로 Serialize되기때문에
 
 lock이 필요 없다는것. ^^)

Case3은 세션을 Datasource에서 가져오기 때문에 사용중인 세션에 SP를 호출하는

우를 범하지 않아서 계속 지역변수로써 Session을 생성하지만 더 빠른것이다.



Connection Pool을 직접적으로 체감하기 위해 스레드생성 이전부터 루프를 돌려 테스트를 진행해 보았다.

10회 // 4296, 3285, 1082, 588
20회 // 8801, 5908, 2118, 1089
50회 // 21883, 7544, 3257, 2585

잼있는 결과가 나온다.

자동으로 생성해준 코드가 DataSource와 Session을 미리 연결해놨을때 보다

훨씬 빠른 속도를 보여준다.

왜 이런 결과가 나온것일까?

DataSource와 Session을 단일하게만 사용했기때문에 Pool을 제대로 활용 못한 결과이다.

즉, DataSource와 Session을 매번 생성하는 Case 1의 경우 Pool을 제대로 활용했기때문에

Case1보다 빠른 성능을 보여준다.

하지만 Case3이 가장 빠를수 밖에 없는 이유는 Connection Pool도 활용하면서

선형적인 작업에는 Session Pool이 사용되는 구조이기 때문에 좋은 성능을 보여준다.

Case4는 Session을 미리 생성해두고 사용하기 때문에 지역변수가 Stack쌓이고 정리되는

과정을 줄여 속도를 높이고 있다.



결론적으로, DataSource는 하나로, Session은 필요할때(SP나 Query를 호출할때)

생성해주는게 좋은 성능을 보여준다.

게다가  Session또한 Pool로 구성하면 더욱 좋은 성능을 낼수 있다.



< vector를 이용해 Session Pool을 구현한 급조 소스 >






추가적으로 ...

<< Connection Pool에 대한 기본 개념  >>

Pool?  자료나 공간에 대해 미리 구성을 한뒤에 뽑아서 사용하고 다시 집어넣는 형식을 말함.

Connection Pool? 상호간의 연결에 대한 풀을 구성해놓고 접속을 재사용하는것.

MSSQL에서의 Connection Pool의 특징

1. Database Connection에 대한 풀.
  즉, OLEDB Provider 기준으로 보자면 CDataSrc에 해당한다.

2. 프로세스 단위로 구성
  각 풀은 프로세스 마다 풀을 구성하게 된다.

3. default값으로 Connection pooling 한다.

조건? Connection String부분이 blank하나까지도 동일해야 한다.
        (UDL파일을 사용하여 실수를 줄일수 있다)

,
Technical Article 2007. 9. 26. 21:21

wchar_t 타입을 받는 형식라이브러리 빌드 문제 C2664 Part 2

MIDL의 파싱 오류라고만 치부하기에는 MSDN의 샘플코드도 문제가 있었다.

이전글에서

 HRESULT hr = m_pSpMgr->S_AddUser( (unsigned short*)("first112"), 0, (unsigned short*)("what"), (unsigned short*)("whatu"));


이런 코드를 사용했는데 TCHAR* 를 이용해서 인자를 전달하지 않고 위에 처럼

문자열 상수를 사용하게 되면 유니코드로 들어가는게 아니라,

일반 ansi char로 인자가 전달되게 된다.

사용자 삽입 이미지
( 이 이미지는 what에 해당하는 부분이 아예 제대로 값이 전달 안되었는데 실제로는 what 0x00 4개가 전달된다 )

제대로 전달하기 위해서 코드는 다음과 같이 해야하며,

 HRESULT hr = m_pSpMgr->S_AddUser( (unsigned short*)_T("first112"), 0, (unsigned short*)_T("what"), (unsigned short*)_T("whatu"));



좀더 C++ 스럽게 표현하면

  HRESULT hr = m_pSpMgr->S_AddUser(reinterpret_cast<unsigned short*>(L"first112"),
           0,
           reinterpret_cast<unsigned short*>(L"what"),
           reinterpret_cast<unsigned short*>(L"whatu"));


이와 같이 해야 맞을것이다.

,
Technical Article 2007. 9. 26. 20:51

wchar_t 타입을 받는 형식라이브러리 빌드 문제 C2664

#include "stdafx.h"
#import "progid:BWDBAgent.SPMgr.1" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
 ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 {
  ISPMgrPtr m_pSpMgr;

  m_pSpMgr = ISPMgrPtr(__uuidof(CSPMgr));

  HRESULT hr = m_pSpMgr->S_AddUser(_T("first1"), 0, _T("what"), _T("whatu"));

 }
 ::CoUninitialize();
 return 0;
}

위와 같은 간단한 코드를 빌드하는데

..\bwdbagenttester\bwdbagenttester.cpp(15) : error C2664: 'ISPMgr::S_AddUser' : 매개 변수 1을(를) 'const wchar_t [7]'에서 'unsigned short *'(으)로 변환할 수 없습니다.
1>        가리킨 형식이 관련이 없습니다. 변환하려면 reinterpret_cast, C 스타일 캐스트 또는 함수 스타일 캐스트가 필요합니다.

이런 에러가 발생하였다.


COM 인터페이스는 다음과 같다.

__interface ISPMgr : IUnknown
{
 [helpstring("메서드 S_AddUser")] HRESULT S_AddUser([in] wchar_t* userid, [in] LONG usertype, [in] wchar_t* password, [in] wchar_t* nick);
};

저번에도 봤었는데 가물가물해서 정리해놓는다.


MSDN에 보면

midl 컴파일러에 있는 버그로 인해 wchar_t 형식이 형식 라이브러리에서 부호 없는 short로 생성됩니다. 이 오류를 해결하려면 C++ 소스 코드에서 형식을 캐스팅하거나 idl 파일에서 형식을 문자열로 정의해야 합니다.




  HRESULT hr = m_pSpMgr->S_AddUser((unsigned short*)("first1"), 0, (unsigned short*)("what"), (unsigned short*)("whatu"));

이렇게 하면 된다.

되도록이면, BSTR을 사용하는게 나을듯 싶다.

최대한 고치지 않고 부분만 빼낼려고 했더니원 -_-;;

,
Technical Article/펌 2007. 9. 15. 19:14

서버 구현할꺼~

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력해주세요.

Technical Article 2007. 8. 23. 11:58

_tcscpy, _tcsncpy, _tcsncpy_s 비교 및 올바른 사용법

TCHAR pszMsg[256];

 _tcscpy(pktSend.pszMsg, _T("Hello~ Everyone~"));// , sizeof(pktSend.pszMsg));

 _tcsncpy(pktSend.pszMsg, _T("5555555555555555"), sizeof(pktSend.pszMsg)); // it's wrong

 _tcsncpy(pktSend.pszMsg, _T("5555555555555555"), _countof(pktSend.pszMsg)); // it's right


_tcsncpy의 count인자는 ( Number of characters to be copied.)

 복사될 글자수를 의미하는데,

 UNICODE나 _UNICODE가 define되어있을때는 wchar가 아닐때는 char가 들어가게 되는데

 sizeof를 사용하게 되면 wchar일때 TCHAR pszMsg[256]이

 wchar pszMSg[256]이 되어 실질적인 사이즈가 516바이트가 된다.
 
 즉 ,다른부분의 스택 영역에 오버런이 발생하게 되는것이다.

 VS2005로 오면서 _countof키워드가 추가되었는데 이 키워드를 이용하게 되면,
 
 Compute the number of elements in a statically-allocated array.
 
 MSDN에 있는 설명대로 배열의 갯수를 반환하게 되는것이다.

  single byte나 multi byte나 신경안쓰고 배열의갯수 = 글자의 갯수로 보게 되면
 
 UNICODE선언 유무에 따라 유니코드인지 안시코드인지 결정하게 되는 스트링 관련
 
 함수들(_tcs 접두어가 붙는 CRT String macro functions)은 sizeof대신에 _countof를
 
 사용하면 된다.

 
 좀더 깊이 있게 살펴보자면 Security Enhanced 함수들도 찾아볼수 있는데,
 
 
  • Parameter Validation. Parameters passed to CRT functions are validated, in both secure functions and in many preexisting versions of functions. These validations include:
    • Checking for NULL values passed to the functions,
    • Checking enumerated values for validity,
    • Checking that integral values are in valid ranges.
  • For more information, see Parameter Validation.
  • There is also a handler for invalid parameters which is accessible to the developer. When an invalid parameter is encountered, instead of asserting and exiting the application, the CRT provides a way to check these problems with the _set_invalid_parameter_handler function.
  • Sized Buffers. The secure functions require that the buffer size be passed to any function that writes to a buffer. The secure versions validate that the buffer is large enough before writing to it, helping to avoid dangerous buffer overrun errors which could allow malicious code to execute. These functions will usually return an errno type of error code and invoke the invalid parameter handler if the size of the buffer is too small. Functions which read from input buffers, such as gets, have secure versions that require you to specify a maximum size.
  • Null termination. Some functions which left potentially non terminated strings have secure versions which ensure that strings are properly null terminated.
  • Enhanced error reporting. The secure functions return error codes with more error information than was available with the preexisting functions. The secure functions and many of the preexisting functions now set errno and often return an errno code type as well, to provide better error reporting.
  • Filesystem security. Secure file I/O APIs support secure file access in the default case.
  • Windows security. Secure process APIs enforce security policies and allow ACLs to be specified.
  • Format string syntax checking. Invalid strings are now detected, for example using incorrect type field characters in printf format strings.
  • Additional security enhancements are described in the documentation for each function.

     
    이런 기능들을 해준다.

    어렵게 생각할것없이 strcpy_s( ... ) ; 이런식으로, 일반 CRT스트링 함수에 _s 접미사를 붙여주면 된다.

    다만 dest영역의 크기를 지정해줘야 하는데, 이부분이 귀찮다면

    #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

    이걸 헤더에 선언해줌으로써 전처리 과정에서 strcpy를 strcpy_s로 바꿔주게 된다.



    마지막으로, _tcsncpy와 _tcsncpy_s의 count부분에 sizeof를 사용해서 두 결과의 차이를 비교해보면

    _tcsncpy(pktSend.pszMsg, _T("5555555555555555"), sizeof(pktSend.pszMsg));

    _tcsncpy_s(pktSend.pszMsg, sizeof(pktSend.pszMsg), _T("5555555555555555"), sizeof(pktSend.pszMsg));

    _tcsncpy는 오버런 됐을때 0x00으로 채우게 되지만,

    _tcsncpy_s는 0xFD로 채워줌으로 바로 access viloation을 발생시켜준다.


  • ,
    Technical Article/펌 2007. 8. 8. 13:22

    Big O Expression

    보호되어 있는 글입니다.
    내용을 보시려면 비밀번호를 입력해주세요.

    TOTAL TODAY