2006년 08월 25일 Posted title : [005]sizeof, _msize는 반드시 상세하게 알아야 함.
이번시간에는 #pragma를 설명하기 전에, 미리 알아두어야 하는 것을 먼저 설명한다.
그것은 sizeof이다.[왜 그런지는 #pragma를 설명할 때 이해를 할 것이다.]

이것만 보고, sizeof 모르는 사람도 있나 생각하는 사람도 있겠지만, 깊이 들어갈수록 정말 어려운 것이다. 하지만 매우 중요하다. 이것 모르면 디버깅 한다고 쌩 고생을 할 수 있다. 이번시간에 꼼꼼히 확인을 하도록 해보자.

사실 sizeof는 매우 간단한 것이다. 그냥 변수의 메모리 크기를 알려주는 기능을 하는 것이다. ‘것이다‘라고 표현을 했는데, 이는 함수도 매크로함수도 아니고, 이는 keyword이다. 그럼 간단한 예제를 살펴보자.

bool b;
char c;
short s;
int i;
long l;
float f;
double d;
char carray[10];
char* cnew = new char[10];
int narray[10];
int* nnew = new int[10];
printf("%d ", sizeof(b)); //1
printf("%d ", sizeof(c)); //1
printf("%d ", sizeof(s)); //2
printf("%d ", sizeof(i)); //4
printf("%d ", sizeof(l)); //4
printf("%d ", sizeof(f)); //4
printf("%d ", sizeof(d)); //8
printf("%d ", sizeof(carray)); //10
printf("%d ", sizeof(cnew)); //4
printf("%d ", sizeof(narray)); //40(=10*sizeof(int))
printf("%d ", sizeof(nnew)); //4

여기서 살펴볼 만한 것은, sizeof(bool)은 1Bytes, sizeof(carray)와 szieof(cnew)이다.
1.bool과 BOOL의 차이점
=> BOOL은 windows.h에서 제공하는 자료구조로 TRUE, FALSE를 가짐
=> sizeof(bool)은 1Bytes, sizeof(BOOL)은 4Bytes
=> bool은 별 문제 생길 것이 없다.
bool b = 2;
if(b==true) printf("bool is true. ");
else printf("bool is false. ");
의 경우 "bool is true."를 출력한다. 이는 b=2에서 0이 아니면 자동적으로 type casting에 의해 1(=true)가 b에 들어가기 때문이다. 컴파일을 해보면 “warning C4305: '=' : truncation from 'const int' to 'bool'”의 경고메세지가 나타나는 것을 볼 수 있다.
=> BOOL은 큰 문제가 생길 수 있다.
BOOL wb=2;
printf("%d ", sizeof(wb));
if(wb==TRUE) printf("BOOL is true. ");
else printf("BOOL is false. ");
의 경우 “BOOL is false.”가 출력된다. 이는 자동적으로 type casting이 안되고(당연 경고메세지도 없음), 그냥 2가 입력되고 TRUE(=1)가 아니기 때문이다. 그럼 “BOOL 변수를 사용하지 않으면 되지 않겠네.”라고 생각을 할 수 있지만 windows program에서 대부분의 API들은 BOOL을 return type으로 하고 있다. 그래서 BOOL이 return type인 API를 체크하는 경우 반드시 FALSE와 비교를 해야 한다. API의 수행이 성공이지만, TRUE값 외에 1이 아닌 값을 return하는 경우가 많기 때문이다. 이러한 에러는 잡는 것이 거의 죽음이다. 사전에 방지해라. 괴롭히고 싶은 사람을 죽이고 싶으면 적극 활용해라.
BOOL WINAPI_EXAMPLE() { ... }
if(WINAPI_EXAMPLE() == FALSE) { ... } or
if(WINAPI_EXAMPLE() != FALSE) { ... }

2.sizeof(carray)와 szieof(cnew)의 차이점
carray는 stack-dynamic variable(예: int n)이므로 memory의 stack 공간에 잡히고, cnew는 explicit heap-dynamic variable(예: new, malloc으로 동적생성 변수)이므로 memory의 heap 공간에 잡힌다. 그 외 static variable(예: static int n)은 전역변수와 함께 static 공간에 잡히고, implicit heap-dynamic variable은 JAVA에는 있지만, C, C++에는 존재하지 않는 variable이다. 각설하고, carray, cnew는 둘다 10Bytes이지만 sizeof는 statck공간에 잡히는 것은 메모리의 크기를 정확히 가져오고, heap 공간에 잡히는 것은 그 주소 크기(어떠한 타입이든 상관없이 32bits 컴퓨터에서 주소는 4Bytes)를 가져오기 때문이다.
int *n1 = new int[10];
int *n2 = new int[10];
memcpy(n1, n2, sizeof(n1));
이럴 경우 4byte(주소크기)만 메모리 카피 되어서, 문제가 될 수 있다. 그래서 sizeof를 사용할 때에는 특별한 경우를 제외하고는 절대 변수를 가지고 사용하지 마라. 타입을 가지고 사용해라.
int *n1 = new int[10];
int *n2 = new int[10];
memcpy(n1, n2, sizeof(int)*10);

별 것 아닌데 설명이 너무 길었나?

다음으로 신기한 함수를 하나 살펴보자. _msize이다. 디버깅을 정말 열심히 해본사람은 이 함수를 본적이 있을 것이고, 그 외에는 별로 본적이 없는 함수일 것이다.

MSDN에서 _msize는 아래와 같이 설명하고 있다.[이때 size_t는 typedef unsigned int size_t 이다]
Required header
//Returns the size of a memory block allocated in the heap.
size_t _msize(void *memblock);

즉, heap 영역의 메모리 크기를 Byte단위로 알려준다.
#include <malloc.h>
int* nnew = new int[10];
printf("%d ", _msize(nnew));
를 수행하면 신기하게 40(=10*sizeof(int))이 출력된다. 하지만, stack 공간의 메모리를 테스트를 하면,
int narray[10];
printf("%d ", _msize(narray));
Debug 모드에서는 run-time error로 “Expression: _CrtlsValidHeapPointer(pUserData)”라는 무시무시한 에러박스가 나타나고 죽어 버린다.


그나마 다행이지만, Release모드에서는 아무런 에러가 발생하지 않고, 동작을 하지만, 동작결과는 자신뿐만 아니라 다른 부분에까지 크게 엄청난 영향을 주어서 잡기도 힘들게 만든다.

지금까지 것을 정리를 하자면 stack 공간에서의 변수의 크기는 sizeof, heap 공간에서의 변수의 크기는 _msize, 하지만 변수의 크기는 변수이름을 사용하지 말고, 타입이름으로 계산을 반드시 하도록 하자. 그럼 _msize를 가지고 어디에 사용할 수 있을까? 메모리 크기야 프로그램을 작성하는 사람이 알고 있고, 별로 쓸데가 없을 것 같다. 하지만 놀라울 정도로 매우 강력한 디버깅 용도로 사용할 수 있다. 예전[001]부터 지금까지의 내용을 충분히 이해하고 있고, 프로그램 실력이 조금 있는 사람이라면 “sizeof, _msize를 이용하여 할당한 메모리의 범위를 초과하는 에러를 잡아내는 매크로 함수를 작성하시오.”라는 문제를 풀 수 있을 것이다. 정답은 다음시간에. 커피한잔씩 하면서 조금은 고민을 해보기를 바란다. 고생, 고민 없는 프로그램 실력 증가는 절대 없다는 것을 명심하기를……. 아무리 좋은 자료를 열심히 읽어도 고민을 하지 않으면 아무런 도움이 되지 않는다는 것을.

너무 길어서 계속 진행을 하기에 무리가 있어서, 다음시간에 추가적인 설명을 하도록 하겠다.

잠시후에 새벽 5시 30분 시내버스->대구공항->대한항공(7시 30분)->제주도->한라산(아마 점심 조금 넘어서 한라산 정상에 있지 않을까? ^^)... 모두들 즐거운 하루가 되기를...
Posted by sally | 2006/08/25 04:37 | programming | 트랙백(1) | 덧글(10)
트랙백 주소 : http://simple21.egloos.com/tb/2431434
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from 미친감자 컴퓨터학원 at 2006/08/25 10:13

제목 : sizeof 는 키워드이다.
%5B005%5Dsizeof%2C+%5Fmsize%B4%C2+%B9%DD%B5%E5%BD%C3+%BB%F3%BC%BC%C7%CF%B0%D4+%BE%CB%BE%C6%BE%DF+%C7%D4%2E sizeof 는 함수가 아니다. _msize 는 힙에 할당한 메모리 사이즈를 확인 할 수 있다. 힙을 카피할때는 sizeof(자료형)......more

Commented by 미친감자 at 2006/08/25 09:20
음..저도 예전에 sizeof란 친구가 어디에 어떻게 만들어 졌는지 확인해볼려고 했던 적이 있었는데 keyword였군요...
Commented by 미친감자 at 2006/08/25 10:12
음 고민하지 않으면 자기것이 안되는것 같아요...
정말 좋은 정보였습니다.
_msize라는것 저도 이제 사용해봐야겠네요
포인터 변수에 할당한 메모리 사이즈가 나오니 좋은데요
저도 sizeof(자료형)*개수 형식으로 하고 있는데..
Commented by 바람 at 2006/08/25 17:42
이제 코드를 받으면 데이터형을 자세히 봐야겠어요. 혹시 나를 죽이려는 의도를 갖고 있지는 않은지... ㅋㅋㅋ
Commented by X at 2006/08/26 01:00
true/false , TRUE/FALSE 차이도 있남?
Commented by X at 2006/08/26 01:01
바람// 모든 사람들이 너랑 같은 생각을 하는 것은 아니다..^^
드물게 나처럼 지극히 평범한 사람도 있다..^^
Commented by X at 2006/08/26 14:37
며칠 전 D님의 전체메일을 읽고나서 봉만큼의 코딩실력을 가지지 않으면 안되겠다는 생각이 든다..--.. 신입생들은 다들 코딩 잘하겠지??
Commented by 바람 at 2006/08/26 15:25
지극히 평범하다 하심은...
Commented by 딩어링 at 2006/08/28 01:48
블로그 내용이 너무 무미건조해지는 것이 아닌지...우려되네요 ㅡ.ㅡ
가뜩이나 삶도 건조한데...
Commented by sally at 2006/08/28 01:55
미친감자//특별한 경우가 아니면 _msize는 사용하지 않는 것이 좋습니다.
바람//바람님을 괴롭히려는 사람이 있을까나.
X//true is TRUE이네요. 차이가 없네요.
if(true == TRUE) printf("true is TRUE.
");
else printf("true isn't TRUE.
");
X, 바람//프로그램실력의 차이는 간단한 것을 얼마나 자세히 알고, 활용할 수 있는 가임. 조금만 노력하면 됨.
딩어링//안그래도 프로그램에 대한 설명이후 블로그 방문자들이 팍팍 줄어들고 있다. -.-
Commented by p김기사q at 2009/06/02 11:16
감사합니다. 퍼가도 되죠? ^^

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶



Get off my back
by sally
rss

skin by 에셈