'Architecture for Software/.NET'에 해당하는 글 2건

여러 다른 언어들과 마찬가지로 C#에서도 효과적인 메모리 관리를 위하여 고유 데이터 타입을 정의해 두고 있습니다.

예를 들어 정수, 문자열, 부동 소수점, Boolean 등에 대한 타입들이 바로 그런 예입니다.

여기서 특이한 점은 C#에서는 데이터 타입을 "값 기반(Value based)"과 "참조 기반(Reference based)"로 구분해두고 있습니다.

중요한 점은 Value based Type의 경우 스택(Stack)에 값들을 할당하며, Reference Based Type의 경우 힙(Heap)에 값들을 할당한다는 점입니다.

만약 다음과 같은 코드가 존재한다면 Value Type일까요? 아니면 Reference Type일까요?

// Assign
int a = 2;
int b = 3;

// Swap Value
b = a;
a = 3;

// Print
Console.WriteLine("a = {0}, b = {1}", a, b);

상기 코드에서 a와 b에 할당된 값들은 모두 스택에 저장됩니다. 즉 Value Type입니다.
따라서 결과적으로 a는 3이란 값을 가지며 b는 모드 2란 값을 가지게 됩니다. 결과적으로 서로의 값은 하나의 스택이란 공간에서 각기 다른 주소를 가진 값으로 저장되어 있어 서로 영향을 받지 않습니다.

하지만 Reference Type의 경우는 다릅니다.

// Assign
Foo a = new Foo();
a.x = 10;
a.y = 20;

// Swap
Foo b = a;
b.x = 20;
b.y = 10;

// Print
Console.WriteLine("a.x = {0}, a.y = {1}, b.x = {2}, b.y = {3}", a.x, a.y, b.x, b.y);

결과적으로 a.x 는 20, a.y 는 10, b.x 는 20, b.y 는 10이 됩니다. 즉 a 객체와 b 객체 모두 같은 저장공간에 값을 저장하고 있으며, 같은 주소를 참조하고 있다는 것입니다.

이것이 Reference Type입니다. Reference Type의 가장 큰 특징은 Heap 공간에 데이터를 저장한다는 것입니다. 또한 Heap에 저장된 데이타 중 어느 곳에서도 참조하고 있지 않으면 주기적으로 무시무시한 가비지 컬렉터(Garbage Collector)에 의하여 Heap안에서 제거된다는 것입니다.

즉 참조 타입은 힙공간에 저장되며, 참조가 없는 경우에는 가비지 컬렉터에 의하여 삭제된다. 라는 특성을 가지고 있습니다.

여기서 한가지 더 알아야 할것이 얕은 복사(Swallow copy)라는 개념입니다. 하나의 객체를 다른 객체로 복사하였을 때 복사본이 원본에 대한 포인터를 가지고 있다는 말입니다. 즉 복사시 원본 메모리의 내역을 복사하여 새로운 메모리 공간에 데이타를 할당하지 않고 기존의 메모리 주소를 가리킬 수 있도록만 한다는 것입니다.

따라서 진정한 의미에서 복사는 아니며 단지 힙 공간을 효과적으로 사용하기 위한 메모리 관리 기법입니다.

이와 반대되는 개념이 깊은 복사(Deep copy)가 있는데, 이것이 힙안에 있는 메모리를 완전하게 새로 복사하여 다른 힙 공간안에 주소를 할당받아 복사하는 개념입니다.

따라서 Reference Type에는 Copy도 Swallow copy Deep copy존재한다는 것을 이해할 필요가 있습니다.


신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret
.NET에 MSIL 역어셈블러(ildasm.exe)가 있어서 MSIL 코드들을 확인할 수 있습니다.
ILDasm.exe는 Intermediate Language Disassembler Utility입니다.

MSIL 역어셈블러는 .NET Framework에서만 실행될 수 있는 어셈블리이며, 어셈블리를 역으로 해석해주는 역어셈블러 프로그램이다.

간단하게 C#으로 작성된 코드의 내역중 Boxing이 수행된 내역을 MSIL을 통하여 확인해보겠습니다.
우선 다음과 같은 코드를 작성합니다.

간단하게 버튼을 하나 만들고 버튼에서 리스트에 1 ~ 100까지 출력하는 코드입니다.
        private void button3_Click(object sender, EventArgs e)
        {
            // Boxing이 일어나는 코드이다.
            for (int i = 0; i <= 100 ; i++ )
            {
                // 묵시적인 Boxing
                listBox1.Items.Add(i);
            }
        }

이를 컴파일 한 후 다음과 같은 경로로 이동합니다.

사용자 삽입 이미지

Visual Studio 2003 명령 프롬프트를 실행합니다.

사용자 삽입 이미지

명령 프롬프트에서 ildasm을 실행합니다.

실행된 MSIL 역어셈블러에서 컴파일된 PE파일을 열면 다음과 같이 나옵니다.

사용자 삽입 이미지

아까 button3를 더블클릭하여 보면 PE 파일로부터 MSIL 코드를 추출할 수 있습니다.


만약 다음과 같은 코드를 MSIL 역 어셈블러에서 살펴본다면 같은 코드로 나올 것입니다.
            ArrayList al = new ArrayList();
            al.Add(button1);
            al.Add(button2);
            al.Add(button3);
            al.Add(button4);
            al.Add(button5);

            Button btn = (Button)al[2];
            btn.BackColor = Color.Red;

            foreach (Button b in al)
            {
                b.BackColor = Color.Green;
            }

            IEnumerator ie = al.GetEnumerator();
            while (ie.MoveNext())
            {
                Button btn2 = (Button)ie.Current;
                btn2.BackColor = Color.Blue;
            }

신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret