관리 메뉴

드럼치는 프로그래머

[C/C++] ZeroMemory() , memset() 차이 본문

★─Programing/☆─C | C++

[C/C++] ZeroMemory() , memset() 차이

드럼치는한동이 2009. 1. 29. 21:35

여러분은 구조체를 초기화 할 때, 어떤 방법을 쓰십니까?

0으로 채워야 한다면요,.

 

보통 세가지 방법들을 많이 쓰실겁니다.

 

먼저 Original C에서 부터 즐겨 사용되어 오던 memset()함수가 있겠고요,

둘째로, 윈도우 프로그래밍에서 자주 사용되는 ZeroMemory 매크로도 있구요

제가 즐겨 사용하는 Struct s = {0}; 등이 있지요.

 

뭐가 다를까요? 은근히 이걸 잘 모르시는분들이 많더라고요.

 

그래서 직접 보여드립니다.

 

우선 간단한 테스트 코드를 작성하고요.

#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    struct S{
        int a;
        int b;
        int c;
        int d;
        char e[20];
    };

 

    S s1;
    ZeroMemory(&s1, sizeof(s1));

 

    S s2 = {0};

 

    S s3;
    memset(&s3, 0, sizeof(s3));

 return 0;
}

컴파일러에서 최적화 옵션을 제거해 줍니다.

 

그리고 디스 어셈블리를 해보는겁니다.

 

결과는 아래에!

 

Release Mode 에서의 Disasembly code
    struct S{
        int a;
        int b;
        int c;
        int d;
        char e[20];
    };

    S s1;
    ZeroMemory(&s1, sizeof(s1));
004017F0  push        24h 
004017F2  push        0   
004017F4  lea         eax,[ebp-70h]
004017F7  push        eax 
004017F8  call        memset (401000h)
004017FD  add         esp,0Ch

    S s2 = {0};
00401800  mov         dword ptr [ebp-4Ch],0
00401807  xor         ecx,ecx
00401809  mov         dword ptr [ebp-48h],ecx
0040180C  mov         dword ptr [ebp-44h],ecx
0040180F  mov         dword ptr [ebp-40h],ecx
00401812  mov         dword ptr [ebp-3Ch],ecx
00401815  mov         dword ptr [ebp-38h],ecx
00401818  mov         dword ptr [ebp-34h],ecx
0040181B  mov         dword ptr [ebp-30h],ecx
0040181E  mov         dword ptr [ebp-2Ch],ecx

    S s3;
    memset(&s3, 0, sizeof(s3));
00401821  push        24h 
00401823  push        0   
00401825  lea         edx,[ebp-28h]
00401828  push        edx 
00401829  call        memset (401000h)
0040182E  add         esp,0Ch

 

뭐 딱 보면 아시겠죠? 워낙에 간단하잖아요.

ZeroMemory랑 memset은 같구요, (똑같이 인자를 스택에 넣고, memset의 주소를 콜하지요?)

 

={0} 은 좀 다른것 같죠?(단순히 0으로 채워 넣는겁니다. "xor ecx, ecx "에서 0을 만들잖아요)

 

ㅋ 근데 뭐 하는 일은 똑같습니다.

 

시간이 좀 있으시면, memset의 주소를 찾아가 보세요.(할 줄 아시면요~) 적잖이 긴 코드에 놀라실지도 모릅니다.

근데 사실,  최적화 옵션 켜고 컴파일하면 거기서 거기에요;

뭐 결론은, 전 웬만하면 ={0}으로 초기화 합니다. 편하잖아요. 가독성도 좋고. 

 

그리고, 더 재미있는게 있는데요!

 

구조체가 엄청 커지면 (쉽게 말하자면, memset을 호출하는게 기계어 코드가 더 짧아질 때 이겠죠) 지가 알아서 memset으로 바꿔줘요!

 

#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <Windows.h>

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


{
    struct S{
        char b[256];
    };

    S s1;
    ZeroMemory(&s1, sizeof(s1));

    S s2 = {0};

    S s3;
    memset(&s3, 0, sizeof(s3));

    return 0;
}

이건 직접 한번 디스 어셈블 해보세요!

 

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

 

Memset의 경우는 메모리를 인자로 받은 char 형 변수(1byte)로 채워주는 것이구요. ZeroMemory는 메모리를 0으로 채워준다는 것이 다릅니다.

memset()과 ZeroMemory()의 오버헤드 차이는 없구요. 좀더 0으로 채우는걸 강조하고 싶다면 ZeroMemory()를 사용하시면 되겠죠?^^

 

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

 

char* buff;
이렇게 있으면 이것을 0으로 셋팅할때

memset( buff, 0, sizeof(char) );
ZeroMemory( &buff, sizeof(char) );

------------------------------------------------------------------------------------
memset 에 비해서 Zeromemory는
단지 memset해줄때 0(0x00)으로 해주는 수고를 들게 해줄뿐이다.
ZeroMemory 는 zero 값밖에 안된다.
memset 은 초기값을 원하는 값으로 줄 수 있습니다.
널값으로 초기화 하고 싶을때는
memset( buff, '/0', sizeof(char) );   (/ -> 역슬러쉬 변경)
------------------------------------------------------------------------------------
매크로 원형

#define ZeroMemory RtlZeroMemory
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
------------------------------------------------------------------------------------
Data type

void *memset( void *dest, int c, size_t count );
VOID ZeroMemory( PVOID Destination, DWORD Length );

------------------------------------------------------------------------------------
여러가지 데이터 타입

TCHAR strTest[100]={"ddddddddddddddddddd"};
memset(strTest,0,sizeof(TCHAR)*100);
::ZeroMemory(&strTest,sizeof(TCHAR)*100);

void이므로 다른 byte,string,structure도 가능 

[출처] http://blog.daum.net/sbshope/7245394

Comments