Finding Optimal Apache Conf.

아파치 튜닝 정리 

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

아파치 튜닝 정리

1. 웹 페이지 로딩시간 확인
#time -pa lynx -source http://www.gwise.com > /dev/null
real 0.74
user 0.16
sys 0.09
-------------
실제 접속시간 : 0.74-(0.16+0.09)=0.49초


2. 아파치 벤치 마킹 
#man ab 사용법 보기
-n requests 요청을 수행할 개수
-c concurrency 요청을 만들 개수로 동시 사용자 개념으로 이해하면 되겠다.
-v verbosity 얼마나 자세한 정보를 화면에 출력해 줄 것인지 결정
-w HTML 문서형식으로 테이블로 만들어 결과를 화면에 출력
-k HTTP 프로토콜의 지속연결 (KeepAlive) 기능을 사용

#./ab -n 100 -c 10 http://www.gwise.com:80/ 
10 명의 유저가 동시에 http://www.gwise.com/index.html 을 요청하는 것을 모의 실험.
각각의 시뮬레이트 유저는 요청을 10 번씩 하게 됩니다

# ab -n 1500 -c 50 http://www.apache.kr.net:80/
요청을 30 x 50 (50 명의 사용자가, 각각 30 번의 요청)

Requests per second: 80.48
초당 80.48개를 요청 했음.

'MaxRequestsPerChild’ 는 메모리 누수현상(?) 등이 발생하지 않는다면 가능한 이 값을 높게 설정하시고요(파라미터의 값을 0 으로 설정해 무한대로 하실수도 있습니다) StartServers’ 는 프로세스가 active 되어 있는 경우가 적을 경우 값을 낮게 설정하시고, 접속량이 아주 많을 경우는 MaxClients 에 가깝게 조절하시기 바라며, MaxSpareServers 를 MaxClients 와 같게 설정합니다. MaxClients 는 너무 낮게 설정하지 않도록 주의하시기 바라며, 그렇다고 또 너무 크게 잡으셔도 안됩니다


3. 웹 서버 삽질 막기
BrowserMatch "WebZip" go_out
BrowserMatch "Teleport" go_out
BrowserMatch "GetRight" go_out



....
Deny from env=go_out


4. 아파치 튜닝
일반 서버에서는 다른것은 그냥 Default 값으로 둔다.
(대형 서버의 경우 말고는 특히 쓸 일어 없을 것이다.)

증가 시킬 경우 배수로 한다. 꼭 이렇게 해야 한다가 아니라
이렇게 하면 좋다.

Timeout 300
클라이언트의 요청에 의해서 Server와 연결 되었을때
클라이언트와 서버간의 아무런 메시지가 발생하지 않았을때
오류로 처리하는 시간
네트워크 속도가 나쁠수록 수치값을 높게 한다.

KeepAlive on
지속적인 접속, 즉 서버 연결에 대하여 한번 이상의 요청을 허용 여부.

MaxKeepAliveRequests 100
클라이언트가 접속된 시간동안 아파치 서버에 요청할 수 있는 처리 process 개수

StartServers 5 X ? =20 -> 초반에 뜰 process 그 이상 그이하의 의미도 없다.
MinSpareServers 5 X ? =20 -> Spare 프로세스가 이것 이하 일때 끌어 올려 준다.
MaxSpareServers 10 X ? =40 -> Spare 프로세스가 이것 이상 일때 진정(?)시켜 준다.
말 그대로 Spare.... 언제 있을지 모를 요청에 대해서 컴퓨터 스스로가 
조절해 준다.

MaxClients 150
클라이언트들이 동시에 최대로 접속했을때 가능한 최대 서버이 수를 지정.
Ulimit -a ~~~ max process...이 수치 이상 증가 못함.
httpd.h
HARD_SERVER_LIMIT=250 조정해서 다시 컴파일 가능

MaxClient 150 -> 동시에 떠 있을수 있는 최대 process
더 많은 수를 원할시 httpd.h 소스 파일의 
HARD_SERVER_LIMIT 값을 수정 한 다음 다시 컴파일 해야 한다.

#ulimit -a
core file size (blocks) 0
data seg size (kbytes) unlimited
file size (blocks) unlimited
max memory size (kbytes) unlimited
stack size (kbytes) 8192
cpu time (seconds) unlimited
max user processes 2048
pipe size (512 bytes) 8
open files 1024
virtual memory (kbytes) 2105343
-----------------------
위의 max user processes 의 수를 초과 할 수 없다.

MaxRequestPerChild 100
한 프로세스가 몇 번의 서비스를 하고 소멸될 것인지 정한다.
M$계열에서는 별 의미가 없으므로 0을 한다.
하지만 Unix 계열은 0을 사용하지 않는 것이 좋다.

가장 중요한 것은Timeout 설정입니다. 위에서 keep-alive 를 설정해 놓은 
경우, 하나의 connection에서 계속해서 다음 request를 처리할 수 있기 때문에 효율적
이라고 하지만, 실제로는 그렇지 않습니다. keep-alive 를 허용하고 그 timeout을 
5초로만 설정해도, 하나의 request를 처리한 후 적어도 5초동안은 그 httpd가 다른 
작업을 하지 못하고 다음 request를 기다리게 됩니다.

보통 웹브라우저들은 서버로 동시에 4개의 connection을 만들게 됩니다. 한 페이지를 
보는데 이미지 등등 해서 보통 4개의 connection을 만드는 것은 기본이죠. 이렇게 되면 
httpd가 100개 떠 있다고 해도, 실제로는 동시에 25명의 방문자밖에 처리하지 못합니다.

그리고 keep-alive timeout이 5초인 경우, 한 명의 방문자를 처리한 후 적어도 5초동안은 
계속해서 기다리면서 httpd가 놀게 됩니다.(그렇다고 해서 httpd의 수를 늘여주면 앞의 
문제 때문에 load가 몰릴 때 순간적으로 부하가 지나치게 많이 걸리게 됩니다. 어떤 
request는 수초가 지난 후 답을 받는 등 quality of service가 많이 떨어지죠.)

결국 한 명의 방문자를 처리하는데 4개의 httpd가 5초동안 작업한다는 뜻이고, 100개의 
httpd를 띄워봐야 1초에 5명의 방문자밖에 처리하지 못하는 셈입니다. ( 1 명 / 5 sec / 
4 httpd = 5 / 1 sec / 100 httpd )

그래서 검색엔진 서비스 등 traffic이 많은 사이트에서는 keep-alive 옵션을 반드시 꺼 
놓게 됩니다. 그리고 connection timeout도 상당히 짧게 설정해 놓죠. 4~5초 이내로 말입니다


5. 아피치 튜닝-2(로그기록 로테이트로)
/home/apache/conf/httpd.conf
CustomLog /home/apache/logs/access_log common
TransferLog "|/home/apache/bin/rotatelogs /home/apache/logs/access_log 86400"
TransferLog "|/home/apache/bin/rotatelogs /home/apache/logs/error_log 86400"
--------------
24시간 마다 로그 화일을 갱신해 준다.
24X60X60=86400초


6. 아파치 에러 메시지 바꾸기
httpd.conf
Customizable error response (Apache style)
2) local redirects
ErrorDocument 404 /cgi-bin/missing404.pl

missing404.pl
---------------
#!/usr/bin/perl
print<<"(END_HTML)";
Content-type: text/htmlnn

요청하신 http://www.gwise.com$ENV{'REQUEST_URI'} 이 존재 하지 않습니다.
서버관리자 에게 문의 바랍니다.

(END_HTML)
exit;
---------------


7. 아파치 에러 코드 
HTTP 1.1 status codes [TOP] 
100 : Continue 
101 : Switching protocols 
200 : OK, 에러없이 전송 성공 
201 : Created, POST 명령 실행 및 성공 
202 : Accepted, 서버가 클라이언트 명령을 받음 
203 : Non-authoritative information, 서버가 클라이언트 요구 중 일부만 전송 
204 : No content, 클라언트 요구을 처리했으나 전송할 데이터가 없음 
205 : Reset content 
206 : Partial content 
300 : Multiple choices, 최근에 옮겨진 데이터를 요청 
301 : Moved permanently, 요구한 데이터를 변경된 임시 URL에서 찾았음 
302 : Moved temporarily, 요구한 데이터가 변경된 URL에 있음을 명시 
303 : See other, 요구한 데이터를 변경하지 않았기 때문에 문제가 있음 
304 : Not modified 
305 : Use proxy 
400 : Bad request, 클라이언트의 잘못된 요청으로 처리할 수 없음 
401 : Unauthorized, 클라이언트의 인증 실패 
402 : Payment required, 예약됨 
403 : Forbidden, 접근이 거부된 문서를 요청함 
404 : Not found, 문서를 찾을 수 없음 
405 : Method not allowed, 리소스를 허용안함 
406 : Not acceptable, 허용할 수 없음 
407 : Proxy authentication required, 프록시 인증 필요 
408 : Request timeout, 요청시간이 지남 
409 : Conflict 
410 : Gone, 영구적으로 사용할 수 없음 
411 : Length required 
412 : Precondition failed, 전체조건 실패 
413 : Request entity too large, 
414 : Request-URI too long, URL이 너무 김 
415 : Unsupported media type 
500 : Internal server error, 내부서버 오류(잘못된 스크립트 실행시) 
501 : Not implemented, 클라이언트에서 서버가 수행할 수 없는 행동을 요구함 
502 : Bad gateway, 서버의 과부하 상태 
503 : Service unavailable, 외부 서비스가 죽었거나 현재 멈춤 상태 
504 : Gateway timeout 
505 : HTTP version not supported

////////////////////////////////////////////////////////////////////
이부분은 트래픽 양이 큰 곳에서 사용하시면 좋습니다.
설정파일에서 참고할 부분들을 적은 것이니, 꼭 이렇게 바꾸실 필요는 없습니다.

MaxKeepAliveRequests 100 -> 10000 
웹서버 프로세스가 지속적으로 접속을 유지하면서 처리할 수 있는 요청 개수입니다.
KeepAliveTimeout 15 -> 30
서버에 접속시에 웹페이지 객체들의 전송시 새로운 프로세스를 생성하지 않고 지속적으로 접속을 유지하고 담당하며, 
이 클라이언트의 요청에 대한 타임아웃에 대한 값입니다.
StartServers 5 -> 20
MinSpareServers 5 -> 20 
MaxSpareServers 10 -> 40
폭주하는 서버일 경우 SpareServer가 많으면 빨리 대처할 수 있습니다.
스탠드얼론 방식일 경우 새로운 접속 요청을 받으면 기존의 Spare Child Process를 포크해 새로운 자식 프로세스를
만들어 내므로 적당히 있어주면 좋습니다.
MaxRequestsPerChild 0 -> 1000
웹서버 프로세스가 일정 횟수의 클라이언트 요청을 처리하고 종료되는 수치입니다.
※ MaxClients 256 -> 1024
동시에 실행될 수 있는 최대 프로세스 수를 제한 하는 것입니다.
하지만 옵션을 1024로 확장하려면 소스레벨에서 
아파치 설치전에 apache/src/include/httpd.h 파일에서
HARD_SERVER_LIMIT 256 으로 된것을 1280 으로 변경한후 컴파일 하여야 사용 가능하다.




Tomcat에서 세션 타임아웃 설정은 적용 우선순위 순서로 다음 세 곳에서 가능합니다. 

(1) 프로그램안의 session.setMaxInactiveInterval() 

(2) 웹어플리케이션의 WEB-INF/web.xml 

(3) Tomcat의 conf/web.xml



 "세션에 접근한 시간을 기준으로" 란 말은 session.setAttribute() 또는 session.getAttribute() 를 했을때 인가요?? 
--> 제가 오해하기 좋게 적었네요.  
Tomcat은 session cookie를 가진 request가 전달되면 해당 session 사용여부와는 관계없이 해당 세션의 last access time을 갱신합니다.
 즉 마지막 http 요청을 받은 시간이 기준이 됩니다.



J2 SE 1.4 이후론 Default Package에 대한 접근이 불가.
(여러 글에서 스펙에 나와있다 하였으나 정확하게 파악하지는 못한상태.)

다음과 같은 방법으로 가능은 함.;


 Class fooClass = Class.forName("FooBar");
 Method fooMethod = fooClass.getMethod("fooMethod", new Class[] { String.class });

String fooReturned =
      fooMethod.invoke(fooClass.newInstance(), new String[] { "I did it"}).toString();

출처.



뭐 여튼 한가지 배웠으니 :)


# 추가.

Sun 홈페이지에서 다음과 같은 문서 발견.



160 페이지에 보면

 It is a compile time error to import a type from the unnamed package



라는 문구..


unnamed package = default package 



찾았다.. 하악하악;

뭔가 이클립스에서 

아름다운 정렬 기능을 보다보니..




VS에도 있을꺼다..

하면서


샛길에서 발견한

단축키 목록;;


무려 PDF 파일로

지원해준다.







이런게 있었네..


Address Off
set
After HeapAlloc() After
malloc()
During
 free()
After HeapFree() Comments
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Win32 heap info
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Win32 heap info
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDD
DDDD
0x00320448 Ptr to next CRT heap block (allocated earlier in time)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDD
DDDD
0x00320448 Ptr to prev CRT heap block (allocated later in time)
0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDD
DDDD
0xFEEEFEEE Filename of malloc() call
0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDD
DDDD
0xFEEEFEEE Line number of malloc() call
0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDD
DDDD
0xFEEEFEEE Number of bytes to malloc()
0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDD
DDDD
0xFEEEFEEE Type (0=Freed, 1=Normal, 2=CRT use, etc)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDD
DDDD
0xFEEEFEEE Request #, increases from 0
0x00320FFC -4 0xBAADF00D 0xFDFD
FDFD
0xDDDD
DDDD
0xFEEEFEEE No mans land
0x00321000 +0 0xBAADF00D 0xCDCD
CDCD
0xDDDD
DDDD
0xFEEEFEEE The 8 bytes you wanted
0x00321004 +4 0xBAADF00D 0xCDCD
CDCD
0xDDDD
DDDD
0xFEEEFEEE The 8 bytes you wanted
0x00321008 +8 0xBAADF00D 0xFDFD
FDFD
0xDDDD
DDDD
0xFEEEFEEE No mans land
0x0032100C +12 0xBAADF00D 0xBAAD
F00D
0xDDDD
DDDD
0xFEEEFEEE Win32 heap allocations are rounded up to 16 bytes
0x00321010 +16 0xABABABAB 0xABAB
ABAB
0xABAB
ABAB
0xFEEEFEEE Win32 heap bookkeeping
0x00321014 +20 0xABABABAB 0xABAB
ABAB
0xABAB
ABAB
0xFEEEFEEE Win32 heap bookkeeping
0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Win32 heap bookkeeping
0x0032101C +28 0x00000000 0x00000000 0x0000
0000
0xFEEEFEEE Win32 heap bookkeeping
0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Win32 heap bookkeeping
0x00321024 +36 0xFEEE0400 0xFEEE
0400
0xFEEE
0400
0xFEEEFEEE Win32 heap bookkeeping
0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32 heap bookkeeping
0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32 heap bookkeeping




원본글
http://www.nobugs.org/developer/win32/debug_crt_heap.html

필요에 의해 STL을 부문부문 사용하다기보단

선배의 한마디 덕에

for_each의 사용법에 대해 궁금해하여

구글링을 통해 msdn 샘플을 사용해 보았다.




샘플 소스 전문


// foreach.cpp
// compile with: /EHsc
//
// Functions:
//   for_each  - Calls function F for every element in a range.
//
//   begin     - Returns an iterator that points to the first element
//               in a sequence.
//
//   end       - Returns an iterator that points one past the end of
//               a sequence.

// disable warning C4786: symbol greater than 255 characters,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// prints the cube of integer n
void PrintCube(int n)
{
    cout << n * n * n << " " ;
}

int main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    int i ;

    // Initialize vector Numbers
    for (i = 0; i < VECTOR_SIZE; i++)
        Numbers[i] = i + 1 ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // for each element in the range [first, last)
    // print the cube of the element
    for_each(start, end, PrintCube) ;
    cout << "\n\n" ;
}



소스전문 끝


실행 결과


Numbers { 1 2 3 4 5 6 7 8  }

1 8 27 64 125 216 343 512





for_each(start, end, PrintCube) ;

대충 이렇게 사용하는거군;




설정부.
    // Define a template class vector of integers
    typedef vector<int > IntVector ;
   
    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;
  
간단한게 사용하기 위해 템플릿(정수 벡터형, 이터레이터)을 선언하고.

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

정수형 벡터를 선언한다음.

    IntVectorIt start, end, it ;

이터레이터로 시작과 끝, 이터레이터를 설정.
// 최후 it는 for_each를 위해서는 구지 필요하지 않다;



포인트는 이녀석

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

Numbers 의 시작과 끝을 start 와 end에 설정.



for_each(start, end, PrintCube) ;

start에서 시작해서 end에서 종료

각 스텝마다 PrintCube를 실행

인자는 자동으로 PrintCube 뒤에 추가된다.

그리하야 PrintCube(*it) 이런식으로 기록하지 않아도 된다;



정확한 설명은 아래 영문이 설명


The for_each algorithm calls Function F for each element in the range [First, Last) and returns the input parameter F. This function does not modify any elements in the sequence.


대중의 의미는.

for_each 는  first, last범위안에 있는 각 요소를  함수 F의 인자로 호출한다.

이 함수는 일련의 요소에 대해서 수정을 하지 않는다.







저 영문을 읽지 않고 뭔가 멋진 방법을 고민하다가.(결론은 쓸대 없는 방법이 되었지만.)

for_each(start,end,PrintIT(it));

이런문장이나.

void PrintIT(iterator n){
 cout << *n << endl;
}

이런함수가 등장해버렸다..

실행결과 유한개의 오류를 뱉어내주어서.

뭔가 하고 msdn참조 역시!...

뻘짓 :)






역시나 이런녀석 한번 알고나면.

어디에 써먹을까 한참 고민만 하다가

다음에 사용하지 않게된다.. ;;;



이러다보면 언젠간 늘겠지 ( --);

LPSTR, LPCSTR, LPTSTR, LPCTSTR, LPWSTR, LPCWSTR 의 의미는 다음과 같다.




LPSTR, LPCSTR, LPTSTR, LPCTSTR , LPWSTR, LPCWSTR
뭔가 다 비슷 비슷해보이죠?

원래 c와 c++은 string이라는 똑똑한 자료구조형을 compiler차원에서 지원하고 있지 않습니다.

그대신 가장 많이 사용하는 string을 어떻게 저장해야 할지에 대해 고심한 결과...
결국 배열의 끝에 '\0'또는 0 또는 NULL값을 넣어 string을 표현하도록 했습니다.
결국 가장 적은 용량의 string처리와 가장 골치아픈 string처리가 탄생하는 순간이였죠.

어쨌거나 요점은...
Windows에서는 이런 string처리를 위해서 char* 형을 그대로 쓰기 보다는 LPCSTR등의 표현으로 대치해 사용함으로써, 개발의 편의성을 돕고 있습니다.

자... 그럼 서론이 길었고...
위의 골치아픈 형을 살펴보면..

같은 글자들이 여러번 반복해 나옴니다.

LP, C, STR 등이 거의 자주 반복되고,
어떤놈들은 T 나 W를 사용하기도 하죠.

글자를 하나씩 살펴볼까요.

LP는 long pointer를 나타내는 약어로서 16bit시절의 윈도우의 유산입니다.
과거 windows3.1까지의 시절에는 포인터는 모두 16bit였고, 24bit 메모리를 long pointer라는 것을 통해서 extended memory라는 이름으로 관리했었거든요..
현재 LP(long pointer)는 .Net에서는 64bit pointer를, VC++6.0과 그 이전 버전에서는 32bit pointer를 나타냅니다.

C는 constant, 즉 함수의 내부에서 인자값을 변경하지 말라는 뜻입니다.

STR은 말그대로 string자료가 될것이라는 뜻으로 내부적으로는 char형 배열에 null값 종료를 의미하고 있죠.

자... 그럼 해석해 봅시다..
LPSTR = long pointer string = char *
LPCSTR = long pointer constant string = const char *
결과적으로는 맨 마지막과 같은 형이라는 거죠.

그런데...
LPCTSTR!! 요넘은 무었이냐!!
LPCTSTR = long pointer constant t_string = const tchar *
앗! 오타입니다. t라는 놈이 들어갔네요..
오타일까요? ^^ 아닙니다. t라는 놈은 우리나라를 위해 아주 중요한 역할을 하는 놈이죠.. 이것은 잠시 이후에 살펴보겠습니다.

그럼 먼저..
W라는 넘을 살펴보죠...

W 이넘은 wide char를 나타냅니다. 쉽게 말하면 unicode죠..
win9x에서 사용하던 multibyte와는 다릅니다. 물론 한글 조합형 코드도 아니고...
unicode를 나타냅니다.

자 그럼 다시 해석을 해보죠.
LPWSTR = long pointer wide string = w_char *
LPCWSTR = long pointer constant wide string = const w_char *

위와 같이 해석됩니다.


그런데 t_char('티캐릭터'라고 읽습니다.)는 무었이냐!!

마이크로소프트가 세계 각국에 제품을 판매하면서..
각국의 언어에 맞추어 개발하는 것에 환멸을 느끼다가..
드디어 windows를 unicode기반으로 개발하는 작업에 착수했습니다.

그런데... 문제는 char는 1Byte이고 wide char는 2Byte이므로..
포인터 연산을 많이하는 c, c++코드는 호환성에 치명적인 문제가 있었죠.
그래서 컴파일러가 precompile option을 보고. 환경에 맞게 동작하는 코드를 작성할 수 있는 새로운 변수 모양의 Macro를 선언하게 되었습니다.
그것이 바로 TCHAR, t_char라는 변수죠.
이놈들은 자신의 운영체제가 multi-byte환경이면, char형으로,
unicode환경이면, w_char, wide char형으로 type casting됩니다.

그래서... 보통 windows 9x, 2000계열의 환경이라면,
LPTSTR = LPSTR = char *
LPCTSTR = LPCSTR = const char *가 됩니다.

그런데..
아마 저 코드에서..
(LPSTR)(LPCTSTR) 형변환을 할때 자세히 보면..
const 라는 키워드만 떼내는거지요...
그러니까 사실은 (char *)(const char *)와 같은 말입니다.
웃기는 형변환이죠..
그럼 없어도 될까요?
^^

없으면 당연히 오류가 나게됩니다.
왜냐면...(LPSTR)CString을 하면.... CString형 자료의 맨 처음 주소부터 char * 형으로 형변환하기 때문이죠.
CString형은 앞의 16Byte를 자료형을 표현하기 위해서 사용하기 때문에, 여기서부터 형 변환을 해주면 엉뚱한 값이 표현되게 됩니다.

따라서 MFC에서 지원하는 CString class는 LPCTSTR라는 함수를 통해서 일단 안전하게 const char * 형으로 바뀐 자료형을 얻어오게 하는거죠.

CString myString;
(LPCTSTR)myString;이라고 해주면..
myString내부의 string 값을 꺼내오게 도와주는 연산자 또는 함수를 사용하게 된겁니다.
즉 (LPCTSTR)이란 놈이 반환값이 const char* 인 함수입니다.
정확하게 표현하면 operator overloading이라는 거지요.

결과적으로 (LPSTR)(LPCTSTR)myString은
myString의 내부 string 자료를 함수를 통해 자료를 꺼내온뒤에, char* type으로 안전하게 바꾸어주는 역할을 하게 되는 거지요.

참고로, 함수의 인자가 char * 인곳에 const char* 형을 넣으면 컴파일 오류가 발생하기 때문에 (LPSTR)을 한번더 앞에 써주어서 강제 type casting을 한 것입니다.

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

무단으로 퍼왔지만 출처는 남깁니다 :)

http://rmsg.tistory.com

잘쓸게요 ㅠ.ㅠ.

Sizeof.. <= C언어에서 명백한 연산자다.




공비군의 질문에 이것저것 검색해보다가.

첫번째로 발견한 KLDP의 글..


그중에서 눈에 띄는건!!1


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

#include

int main(int argc, char *argv[])
{
int len = -1;

printf("%d %d\n",len,sizeof(int));

if(len > sizeof(int)) printf("BIG\n");
else printf("small\n");

return 0;
}

위 코드의 결과는 무었이라고 예상합니까?

저는 small이 출력되길 원했는데.. BIG이 출력되네요.. 제 코드 버그 찾던 중 발견했습니다.
원인이 무엇인가요?

원본링크 : http://kldp.org/node/72508
////////////////////////////////////////////////////////////////////////////////

잘 생각해보니.. small이 나와야 하는데 왜? -_-;;;

문제는 sizeof의 리턴 타입..


그 답은 역시 KLDP답게 댓글에~


////////////////////////////////////////////////////////////////////////////////
sizeof

Returns the size of the expression or type.

Keyword sizeof is, in fact, an operator. It returns the size, in bytes, of the given expression or type (as type size_t). Its argument may be an expression of a type name:

sizeof expression
sizeof (type)

typedef unsigned long size_t;

#include

int main(int argc, char *argv[])
{
int len = -1;
unsigned long size = 4;

//printf("%d %d\n",len,sizeof(int));
printf("%d %d\n",len,size);

//if(len > sizeof(int)) printf("BIG\n");
if( len > size ) printf("BIG\n");
else printf("small\n");

return 0;
}
////////////////////////////////////////////////////////////////////////////////

간단하게 요약해보면

sizeof의 리턴타입은(연산자 주제에 리턴타입이라니!!) unsigned ..

얼래;; -_-

unsigned x  =0
x-1 = 조낸큰값..


간단 요약이었습니다....



오늘하루도 보람차게~



P.S 토익 ;;; 싸우자;

void Tokenize(const string& str, vector<string>& tokens,
const string& delimiters = " ") { // 처음에 나와있는 구분자들을 건너뜁니다. string::size_type lastPos = str.find_first_not_of(delimiters, 0); // 첫번째 "구분자가 아닌 문자"를 찾습니다. string::size_type pos = str.find_first_of(delimiters, lastPos); while (string::npos != pos || string::npos != lastPos) { // 토큰을 찾았으면 이것을 vector에 추가합니다. tokens.push_back(str.substr(lastPos, pos - lastPos)); // 구분자를 건너뜁니다. "not_of"에 주목하세요. lastPos = str.find_first_not_of(delimiters, pos); // 그다음 "구분자가 아닌 문자"를 찾습니다. pos = str.find_first_of(delimiters, lastPos); } }










레드위키에서 퍼왔습니다.
잘쓰겠습니다.
원 출처는
http://linuxselfhelp.com/HOWTO/C++Programming-HOWTO-7.html

라네요


벡터의 정의 : 방향과 크기를 가지는 것

D3DXVECTOR3

 

백터의 길이 : FLOAT D3DXVec3Length(CONST D3DXVECTOR3* v)

 

벡터의 정규화 : 크기가 1인 단위벡터만들기

D3DXVECTOR3 * D3DXVec3Normalize(

D3DXVECTOR3* pOut,

CONST D3DXVECTOR3* v

)

 

벡터의 내적 : 조명의 계산, 은닉면 처리에 활용

FLOAT D3DXVec3Dot(

CONST D3DXVECTOR3* v1,

CONST D3DXVECTOR3* v2

)

 

벡터의 외적 : 면의 법선 벡터 계산, 평면의 식 계산에 활용

D3DXVECTOR3* D3DXVec3Cross(

D3DXVECTOR3* pOut,

CONST D3DXVECTOR3* v1,

CONST D3DXVECTOR3* v2

)

 

행렬

D3DXMATRIX *D3DXMatrixIdentity

 

전치행렬

D3DXMATRIX *D3DXMatrixTranspose(

D3DXMATRIX *pOut,

CONST D3DXMATRIX *pM

)

역행렬

D3DXMATRIX *D3DXMatrixInverse(

D3DXMATRIX *pOut,

FLOAT *pDeterminant,

CONST D3DXMATRIX *pm

)

 

회전행렬

D3DXMATRIX *D3DXMatrixRotationX(

D3DXMATRIX *pOut,

FLOAT angle

)

 

확대 축소행렬

D3DXMATRIX *D3DXMatrixScaling(

D3DXMATRIX *pOut,

FLOAT sx,

FLOAT sy,

FLOAT sz

)

 

평행 이동행렬

D3DXMATRIX *D3DXMatrixTranslation(

D3DXMATRIX *pOut,

FLOAT x,

FLOAT y,

FLOAT z

)

 

포인트변환 : 지정됭 행렬에 의해 3D 벡터를 변환해, 그 결과를 w = 1 에 투영

D3DXVECTOR3 *D3DXVec3TranformCoord(

D3DXVECTOR3 *pOut,// 결과

CONST D3DXVECTOR3* pV,// 변환할 포인트

CONST D3DXMATRIX* pM// 변환행렬

)

 

벡터변환 : 지정된 행렬에 의해 3D 벡터 법선을 변환

D3DXVECTOR3* WINAPI D3DXVec3TranformNormal(

D3DXVECTOR3 *pOut,// 결과

CONST D3DXVECTOR3* pV,// 변환할 벡터

CONST D3DXMATRIX* pM// 변환행렬

)

 

평면 : 점과 법선 벡터를 이용한 평면 구하기?

D3DXPLANE* D3DXPlaneFromPointNormal(

D3DXPLANE* pOut,// 평면

CONST D3DXVECTOR3* pPoint,// 평면상의 포인트

OCNST D3DXVECTOR3* pNormal,// 평면의 법선

)

 

D3DXPLANE* D3DXPlaneFromPoint(

D3DXPLANE* pOut,// 평면

CONST D3DXVECTOR3* pV1,// 평면상의 포인트1

CONST D3DXVECTOR3* pV2,// 평면상의 포인트2

CONST D3DXVECTOR3* pV3,// 평면상의 포인트3

)

평면 법선 벡터의 정규화

D3DXPLANE* D3DXPlaneTransform(

D3DXPLANE* pOut,// 평면

CONST D3DXPLANE *pP,// 입력 평면

CONST D3DXMATRIX* pM// 변환행렬

)

 

포인트와 평면 공간관계

FLOAT D3DXPlaneDotCoord(

CONST D3DXPLANE* pP, // 평면

CONST D3DXVECTOR3* pV// 포인트

)

 

평면변환

D3DXPLANE* D3DXPlaneTransform(

D3DXPLANE* pOut,// 평면

CONST D3DXPLANE* pP,// 입력평면

CONST D3DXMATRIX* pM// 변환행렬

)

 

DirectX는 왼손 좌표계

중지 X축 엄지 Y축 검지 Z축

 

--------

다 외워주마...

(퍼온거 아네요 ㅡ.ㅜ;)

+ Recent posts