BOOL PostThreadMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam);

다른 스레드의 메시지 큐에 메시지를 붙일 때 사용한다. 윈도우 핸들 대신 스레드의 ID 를 첫 번째 인수로 지정해 준다. 이때 이 메시지를 받을 스레드는 반드시 스레드 큐를 가지고 있어야 하는데 큐를 가지지 않는 Worker 스레드는 메시지를 받지 못한다.



[그림] PostMessage 와 SendMessage 가 메시지를 넣는 지점

 

출처: 김상현 API 완전정복...

include <stdio.h>

int main(void)

{

int x,y,sum;

printf("첫번째숫자를입력하시오:");

scanf_s("%d",&x);

printf("두번째숫자를입력하시오:");

scanf_s("%d",&y);

sum= x+y;

printf("두수의합:%d \n",sum);

return 0;

}

위의 워닝은 scanf_s 를 사용하시면 해결하실수 있습니다.


그게 아니면

alt + F7을 누르셔서 속성에 보시면은..

구성속성 -> C/C++ -> 고급에 특정경고사용안함에 4996을 쳐주시고 확인을 누르시면

위와같은 워닝이 없어지는걸 보실수 있으실겁니다.

메모리 버그나 누수는 고치는 것이 어려운게 아니라 발견하는게 어렵다. 메모리 누수나 침범을 쉽게

발견하려면 메모리 관리자의 도움이 필요하다. Win32의 경우 C 런타임 라이브러리의 디버그 힙이 그러한

도움을 제공한다.

디버그 힙은 초기화되지 않은 메모리나 해제된 메모리에 다음과 같은 특별한 값들을 설정한다.

 

* 힙에 할당된, 초기화되지 않은 메모리는 0xCDCDCDCD로 설정된다.

* 스택에 할단된, 초기화되지 않은 메모리는 0xCCCCCCCC로 설정된다.

* 해제된 힙 메모리는 0xFEEEFEEE로 설정한다. (이후 재할당되면 다시 0xCDCDCDCD가 된다)

메모리가 해제되는 방식에 따라서는 해제된 메모리가 0xDDDDDDDD로 설정될 수도 있다.

* 힙에 할당된 메모리의 첫 부분과 끝 부분은 0xFDFDFDFD로 설정된다.

 

디버거에서 메모리 창을 들여다 볼 때 이 값들을 기억하고 있으면 메모리 블럭이 어떤 상태인지 알 수 있다.

 

C 런타임의 디버그 힙은 또한 힙을 조사하기 위한 몇 가지 함수들도 제공한다. 여기서는 다음 세가지만

이야기하겠다. 나머지는 Visual Studio 도움말이나 MSDN을 찾아 보기 바란다.

 

* _CrtSetDbgFlag( int newFlag): 디버그 힙의 행동 방식을 설정한다.

* _CrtCheckMemory( void): 디버그 힙을 점검한다.

* _CrtDumpMemoryLeaks( void): 메모리 누수 상황을 stdout에 출력한다.

내용 출처: Game Coding Complete (정보문화사) 책 본문중에서...

[출처] 게임 디버깅|작성자 baek2187

system 마다 차이가 있지만 기본적으로 메모리 할당은 4Byte 단위로 이루어지기 때문에,

struct 구조체 멤버 변수는 연속된 값을 가지지 못함.

따라서 하기와 같이 해야 1 byte씩 struct 내용을 채울 수 있다

 

#pragma pack(1)

typedef struct customer{
char name;
int height;
int weight;
}customer_type;

 

customer_type kim;

sizeof(kim) ==> 9 byte 크기를 갖음

 

#pragma pack(1)을 선언하지 않으면

#pragma pack(4)를 선언한것 같이 default 인 4byte로 할당되어

 

customer_type kim;

sizeof(kim) ==> 12 byte 크기를 갖음

VS.NET(VS2002)에서 MFC 프로젝트로 만들었던 프로그램을 VC++10 프로젝트로 변환하여 컴파일 했더니 에러가 발생하면서 아래의 경고가 나왔습니다.

C:\Program Files\Microsoft Visual Studio 10.0\VC\atlmfc\include\atlcore.h(35):#error This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended.

 

 

에러 내용은 프로젝트에서 정의된 _WIN32_WINNT 버전이 0x403인데 atlcore.h 버전이 최소 0x0501 이상이 되어야 한다는 것입니다.

그래서 _WIN32_WINN 정의한 stdafx.h 파일을 열어보니

#define _WIN32_WINNT 0x0400

 

 

되어 있었더군요. 그래서 일단 이것을 최신이 좋다라는 생각에 아래와 같이 했습니다. ^^;;

#define _WIN32_WINNT 0x0600

 

 

그랬더니 이제는 아래와 같은 에러가 나오더군요. -_-;

c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afxcmn3.inl(29): error C2065: 'CCM_SETWINDOWTHEME' : 선언되지 않은 식별자입니다.

그래서 바로 구글링 들어갔습니다.

쉽게 저와 같은 에러가 나와서 질문을 올린 글을 찾았고 답변도 보았습니다.

문제 해결은 stdafx.h 파일에 정의된 버전의 숫자를 아래와 같이 하면 된다고 하더군요

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif

#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif

#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0500 // Change this to the appropriate value to target IE 5.0 or later.
#endif

 

 

이렇게 하니 문제 없이 빌드가 성공 되었습니다.

주위에서 VC++의 새로운 버전이 나와도 쉽게 사용하지 못하는 경우가 오래 전에 만들었던 프로젝트를 포팅 할 수 없어서 이전 버전을 어쩔 수 없이 사용한다는 이야기를 종종 듣습니다.

그러나 저는 운이 좋아서인지 2002버전부터 순차적으로 새 버전의 VC++을 사용할 수 있어서 VC++6에서 VS2002로 넘어갈 때만 빌드 문제를 겪었습니다.

그래서 이런 포팅에 대한 문제는 잘 알지 못합니다. 이번에는 예전에 만들었던 코드를 C++0x 코드로 바꾸고 싶어서 오래 전에 만들었던 프로젝트를 VC++ 10로 포팅하면서 정말 정말 오랜만에 이런 문제를 겪어 보게 되고 해결 방법을 포스팅 할 수 있었습니다.

혹시 앞으로 또 이런 경우가 발생하면 바로 바로 공유하도록 하겠습니다.

 

Visual Studio 2003을 비스타 및 Windows 7 에서 쓰기...

2009/11/11 11:16 | Posted by 하트바다 에서 발췌함..

나는 나름 프로그래머이다.
게다가 시리얼과 PCI 통신 등 주로 하위계층의 프로그래밍을 할 때가 많다.
그러기에 나의 입장에서 가장 좋은 버전은 바로 Visual Studio 2003 버전이다.
솔직히 Visual Studio 6 가 가장 작고 많이 쓰는 것은 사실이다.
하지만, Visual Studio 6의 경우는 더이상 도움말 지원이 되지 않고 Windows XP 의 고유 기능을 사용하려면 기본적으로 Platform SDK 를 깔아야 한다.
그리고 나의 경우는 API를 가지고 많이 프로그래밍을 하는데 Visual Studio 2003 부터 API 레벨에서도 CString 이 사용가능하다!!!
이런 멋진 기능으로 인해 아직도 거의 모든 프로그래밍을 Visual Studio 2003 을 이용한다.

각설하고...
문제는 이 VS2003 이 비스타와 Windows7을 만나면 문제가 생긴다.
가장 큰 문제는 아래와 같다.


위의 화면은 VS 를 쓰는 분들은 누구나 아시는 바로 검색창!!!
그런데 문제는 이 검색창을 쓰면 바로 죽어버린다.
바로 아래와 같이...


그런데 VS 에서 가장 중요한 것이 바로 이 검색창....
그래서 찾아보니 역시 답이 있었다.
이 검색창의 Intellisence 를 사용할때 충돌나는 것이 바로 Aero 라는 것이다.
그 Aero 만 죽이면 잘 작동한다.
그렇다고 VS 땜에 Aero 를 죽이는 것은 안타까운 일...
그래서...

C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe 까지 간다.
이 파일이 Visual Studio 의 개발창이다.
이 exe 파일 선택 후 오른쪽 버튼 클릭, 속성창으로 간다.


속성창의 두번째 호환성으로 가면 위의 빨간색 테두리의 시각 테마 사용 안 함에 체크!!!!
이것만 하면 Aero 를 강제로 막아준다.
그렇다고 애매하게시리 2000 스타일로 뜨거나 하지는 않는다.
다만, 메뉴창 등의 시각효과 등은 없어진다.

 

 

위의 화면과 같이 검색이 매우 잘되는 것을 알 수 있다.
다음에 비스타 이후 버전의 Windows 에서 쓸 때는 이 방법을 이용하면 Visual Studio 2003 을 원활히 사용할 수 있다

 

자신의 컴퓨터 환경에 따라 자료형을 메모리에 읽어들이는 것이 다를 수 있다.
운영체재에 따라 default 로 packing 되어 있는 값이 다를 수 있다는 의미다.

회사에서 실제 작업하다가. 정상적으로 빌드는 되지만 실행을 시켜 보니 데이타와의 소스상의 구조체 사이즈가 계속 틀리다고 나오는 것이다. 해결 한답시고 몇십분을 허비했다.


실제 데이타와 구조체 사이즈를 비교해 보면 구조체 사이즈가 크다.
1084 Byte 가 나와야 되는데, 소스상의 구조체 사이즈가 크기가 너무 크게 나온 것이다.
처음 언급했듯이 운영체재의 환경에 따라 packing 되어 있는 크기가 있기 때문이었다. 만약 운영체재에서 packing 된 값이 4 Byte 라고 한다면, char 자료형도 1 Byte가 아닌 4 Byte를 잡고 들어간다. 3 Byte 만큼이 더 커진 것이다. 물론 int 자료형이면, 4 Byte 값이 들어가겠지만, 특정 자료형이 5 Byte 면. 우선 4 Byte 크기를 잡고 나머지 1 Byte 를 잡아주기 위해서 4 Byte 다시 잡아준다.
그래서 5 Byte 자료형은 8 Byte 만큼의 크기를 갖게 되는 것이다.

이런 문제를 막아주기 위해서 #pragma pack(push, 1) 또는 #pragma pack(1) 를 사용하면 운영체재에서 packing 되어진 값이 아닌 1 Byte 씩 자르기 때문에 char 자료형은 4 Byte 가 아닌 1 Byte 가 되고, 5 Byte 형 자료형도 8 Byte 가 아닌 5 Byte 가 된다.

사용 방법은 아래 와 같고, #pragma pack(push, 1) 를 해 주면 반드시 #pragma pack(pop) 를 해 주어야 한다.

#ifndef _Ut_World_h_
#define _Ut_World_h_

#include "World.h"

#pragma pack(push, 1)

struct _ut_world : public _world
{
enum { make_prob = 10000 };

DWORD m_dwTempKing;
_str_code m_strTempLife;
BOOL m_bTempCar;
_str_code m_strTempBurberry;
int m_nTempPolo;

enum { max_num = 5 };
struct _material
{
_itm_code m_itmTempShow;
DWORD64 m_dwTempCyon;
int m_nTempComputer;
};
_material m_Material[max_num];

BOOL m_bTempOver;
int m_nTempPower;

enum { max_out_num = 24 };
struct _out
{
_itm_code m_itmTempCpp;
DWORD64 m_dwTempGigabyte;
int m_nTempKorea;
DWORD m_dwTempScreen;
DWORD m_dwTempServer;
int m_nTempNumber;
};
_out m_Out[max_out_num];

_ut_world()
{
ZeroMemory( this, sizeof( *this ) );
}
};
#pragma pack(pop)

#endif

Union 사용하여 little/big endian 확인.

 

이번 시간은 union(공용체)와 BitField에 대해서 알아보도록 하자.

예전에 번외편으로 Little Endian방식을 쓸때 구조체, union과 비트필드를 이용했다.

개별로는 많이 쓰이지 않기 때문에 이번시간에도 통틀어서 설명하겠다.

 

union에 대해서 간략하게 알아보자.

union은 공용체라고 불리운다.

선언 방식은 위의 코드처럼 전역으로 쓰이는 경우가 대부분이며, 구조체와 같은 형태를 가진다.

하지만 구조체와는 다른방식으로 데이터를 관리한다.

 

모든 공용체안의 멤버변수들은 같은 메모리 공간안에 자리를 잡고 쓰여지게 된다.

이걸 도식화해서 보기로 하자.

 

옆에 파란글씨고 써있는 부분이 도식화 할때 쓰인 코드다.

4Byte의 int형 iNum이란 변수 하나와 1Byte char형 ch란 변수

총 두개의 변수를 U란 공용체 안에 멤버로 선언했다.

메모리의 도식화는 저런 방식으로 된다.

공용체의 모든 멤버변수들은 같은 메모리의 공간을 공요하게 된다.

그래서 공용체의 크기는 제일큰 멤버변수의 DataType의 크기를 가지게 된다.

여기에서는 int형이 제일 커서 4Byte를 가진 공용체가 만들어 지는 것이다.

 

간략하게 공용체의 설명과 도식화를 보여드렸다.

 

자 이쯤에서 예제코드등장!

 

 

이제 이 소스코드를 보기로 하자.

제일 처음에 공용체 U를 선언했다 그리고 그 안에 구조체로 int형 변수 4개를 선언했다.

 

 

위의 코딩을 도식화 해보면 이렇게 나타나게 된다.

union안에는 Total이라는 int형 변수를 선언하고 구조체로 int형 변수를 4개 선언했다. 이때 주의할 점은, 구조체 안의 int형 변수는 각각 1Byte씩만 사용할수 있게 비트필드로 제한을 두었다. 비트필드란 변수의 특정비트만 사용할수 있게 만들수 있는 일종의 기법이다.

변수명 뒤에 " : 사용할 Bit수"를 적어주게 되면, 그에 해당하는 Bit만 사용할수 있게 된다. 여기서 보면 int형은 총 32Bit를 사용하지만 비트필드로 8Bit만 사용할수 있게끔 만들어 놓았다.

 

*BitField란! 하나의 메모리를 여러개의 Label을 붙여 쓰는것을 의미한다.

 

이게 뜻하는건 뭘까?

union안에 있는 Total이란 변수에 자료를 넣으면, 8Bit단위로 쉽게 꺼내올수 있다는걸 의미한다.

 

결과를 보도록 하자.

 

 

Ttotal 12345687를 넣었는데 union과 BitFIeld의 특성 때문에 1Byte씩 액세스 되는걸 볼수 있다.

숫자가 뒤집어 들어가는건 Little Endian때문인데, 그건 번외편을 보도록 하자.

 

공용체와 BitField는 이쯤에서 설명을 마치도록 하겠다.

많이 쓰이진 않지만, 주로 쓰이는 곳을 보자면, 위와 같은 특성때문에,

패킷연산이나, 고스톱알고리즘에 쓰이게 된다.

 

여기서 주의할점은 BitFiled가 진짜로 메모리에 어떻게 작용하는지 알려면,

#pragma pack(1)을 해주고 BitFiled가 정확히 메모리를 어떻게 쓰는지 알수 있다.

#pragma pack()의 기본 디폴트값은 4다.

예전에도 말했듯이 Intel CPU는 4Byte씩 메모리를 액세스 하기 때문에, 제대로된 내용을 파악하기 힘들다.

하지만 #pragma pack(1) 이것을 선언후에 하면 메모리 액세스를 1Byte씩 하게 된다.

그래서 정확한 BitField의 모습을 볼수 있다. 하지만, 액세스가 1Byte씩 일어나기 때문에, 전체적인

퍼포먼스가 떨어진다. 그래서 만약 실제 코딩때 쓴다면, 원래대로 #pragma pack(4), #pragma pack()

으로 돌려줘야 한다.

 

이쯤에서 이번장은 마치기로 하자.

뭔가 빨리 지나간 느낌이 있지만, 그만큼 드물게 쓰이기 때문에, 좀더 자세한 내용을 알고 싶다면,

따로 공부하시는걸 추천한다. 지금껏은 맛배기!

사용해보자.

 

// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
std::vector<int> anVector;
CArray<int> ary;

for(int i=0; i<10; i++)
{
anVector.push_back(i+1);
ary.InsertAt(i, i*10);
}

CString strbuf;
size_t ns = anVector.size();
size_t ns2 = ary.GetSize();
strbuf.Format("vector/Ary Count: %02d, %02d\r\n", ns, ns2);
m_editOutput.ReplaceSel(strbuf);
for(int i=0; i<ns; i++)
{
strbuf.Format("%02d, Data: %02d, %02d\r\n", i+1, anVector[i], ary[i]);
m_editOutput.ReplaceSel(strbuf);
}

 

그리고 Vector 동적 할당 방법은 아래에서 발췌했다.

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

이전까지는 임시로 동적 크기의 버퍼를 생성할 때 보통 아래처럼 작성했었다.

void Function()
{

std::size_t bufferSize = 100 ;
char *pBuffer = new char[ bufferSize ] ;
...
Delete [] pBuffer ;

}

하지만 ... 이부분에서 예외가 발생한다면 pBuffer 는 메모리 누수가 발생할 것이다.
이런 예외가 한두어번에 그친다면 해당 예외가 발생할때에 " Delete [] pBuffer " 를 할수도 있겠으나
그 이상이 된다면 손이 아프게 Ctrl + C, V 를 해야 할 것이고 코드의 간결성도 놓쳐버릴 것이다.

그러나 std::vector< char > 를 쓴다면 이런 문제에서 해방될 수 있다.

void Function()
{

std::size_t bufferSize = 100 ;
std::vector< char > vecBuffer ;
vecBuffer.resize( bufferSize ) ;
....

}

위의 코드로 고친다면 ... 부분에서 예외가 생긴다고 해도 메모리 누수의 위험에서 해방될 수 있다.

[출처] std::vector< char > 로 임시 버퍼를 만들자.|작성자 대장장이

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

이중 포인터 쓰고 지우기..
char **pp;
pp = new char * [NUM1];
for( i = 0; i < NUM1; i++) *(pp+i) = new char[NUM2];

지우기.


for( i = 0; i < NUM1; i++) delete [] *(pp+i);
delete [] pp;

 

+ Recent posts