์นดํ…Œ๊ณ ๋ฆฌ ๋ณด๊ด€๋ฌผ: C#

C#

๊ตฌ์กฐ์ฒด ์ •๋ ฌ์ด ํ•„๋“œ ์œ ํ˜•์ด ๊ธฐ๋ณธ์ธ์ง€ ์‚ฌ์šฉ์ž ์ •์˜์ธ์ง€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? void Main()

์—์„œ ๋…ธ๋‹ค ์‹œ๊ฐ„ V2, ์šฐ๋ฆฌ๋Š” ๋‚˜๋…ธ์ดˆ ํ•ด์ƒ๋„๋กœ ์ด๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์žˆ๋Š” ์ „์ฒด ์‹œ๊ฐ„ ๋ฒ”์œ„๋ฅผ ๋‚˜ํƒ€ ๋‚ด๊ธฐ ์œ„ํ•ด ๋” ์ด์ƒ 8 ๋ฐ”์ดํŠธ ์ •์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด Noda Time์˜ (๋งŽ์€) ๊ตฌ์กฐ์ฒด์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์กฐ์‚ฌํ•˜๊ฒŒ๋˜์—ˆ๊ณ  ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ €๋ฅผ ์ด๋Œ์—ˆ์Šต๋‹ˆ๋‹ค. CLR์˜ ์ •๋ ฌ ๊ฒฐ์ •์—์„œ ์•ฝ๊ฐ„์˜ ์ด์ƒํ•œ ์ ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฒซ์งธ, ๋‚˜๋Š” ์ด๊ฒƒ์ด ์‹คํ˜„ ์ด๋‹ค ๊ธฐ๋ณธ ๋™์ž‘์€ ์–ธ์ œ๋“ ์ง€ ๋ณ€๊ฒฝ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๊ตฌํ˜„ ๊ฒฐ์ •ํ•˜๊ณ ์žˆ๋‹ค. ๋‚˜๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ๊ฒŒ ์ˆ˜ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜์ • [StructLayout]ํ•˜๊ณ  [FieldOffset],ํ•˜์ง€๋งŒ ๋‚œ ์˜คํžˆ๋ ค ๊ฐ€๋Šฅํ•˜๋ฉด์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ์†”๋ฃจ์…˜์„ ๊ฐ€์ง€๊ณ  ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ํ•ต์‹ฌ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” struct์ฐธ์กฐ ์œ ํ˜• ํ•„๋“œ์™€ ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ ๊ฐ’ ์œ ํ˜• ํ•„๋“œ๋ฅผ ํฌํ•จํ•˜๋Š”์ด ํ•„๋“œ์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ๋ž˜ํผ์ž…๋‹ˆ๋‹ค int. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด 64 ๋น„ํŠธ CLR์—์„œ 16 ๋ฐ”์ดํŠธ๋กœ ํ‘œํ˜„ ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž ์ง€๋งŒ (์ฐธ์กฐ ์šฉ์œผ๋กœ 8 ๋ฐ”์ดํŠธ, ๋‚˜๋จธ์ง€ ์šฉ์œผ๋กœ 4 ๋ฐ”์ดํŠธ) ์–ด๋–ค ์ด์œ ๋กœ 24 ๋ฐ”์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ €๋Š” ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณต๊ฐ„์„ ์ธก์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ ˆ์ด์•„์›ƒ์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ํ•ฉ๋ฆฌ์ ์ธ ์‹œ์ž‘์ ์ฒ˜๋Ÿผ ๋А๊ปด์กŒ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๋ฌธ์ œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์ƒ˜ํ”Œ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.

using System;
using System.Runtime.InteropServices;

#pragma warning disable 0169

struct Int32Wrapper
{
    int x;
}

struct TwoInt32s
{
    int x, y;
}

struct TwoInt32Wrappers
{
    Int32Wrapper x, y;
}

struct RefAndTwoInt32s
{
    string text;
    int x, y;
}

struct RefAndTwoInt32Wrappers
{
    string text;
    Int32Wrapper x, y;
}    

class Test
{
    static void Main()
    {
        Console.WriteLine("Environment: CLR {0} on {1} ({2})",
            Environment.Version,
            Environment.OSVersion,
            Environment.Is64BitProcess ? "64 bit" : "32 bit");
        ShowSize<Int32Wrapper>();
        ShowSize<TwoInt32s>();
        ShowSize<TwoInt32Wrappers>();
        ShowSize<RefAndTwoInt32s>();
        ShowSize<RefAndTwoInt32Wrappers>();
    }

    static void ShowSize<T>()
    {
        long before = GC.GetTotalMemory(true);
        T[] array = new T[100000];
        long after  = GC.GetTotalMemory(true);        
        Console.WriteLine("{0}: {1}", typeof(T),
                          (after - before) / array.Length);
    }
}

๊ทธ๋ฆฌ๊ณ  ๋‚ด ๋žฉํ†ฑ์˜ ์ปดํŒŒ์ผ ๋ฐ ์ถœ๋ ฅ :

c:\Users\Jon\Test>csc /debug- /o+ ShowMemory.cs
Microsoft (R) Visual C# Compiler version 12.0.30501.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.


c:\Users\Jon\Test>ShowMemory.exe
Environment: CLR 4.0.30319.34014 on Microsoft Windows NT 6.2.9200.0 (64 bit)
Int32Wrapper: 4
TwoInt32s: 8
TwoInt32Wrappers: 8
RefAndTwoInt32s: 16
RefAndTwoInt32Wrappers: 24

๊ทธ๋ž˜์„œ:

  • ์ฐธ์กฐ ์œ ํ˜• ํ•„๋“œ๊ฐ€์—†๋Š” ๊ฒฝ์šฐ CLR์€ Int32Wrapperํ•„๋“œ๋ฅผ ํ•จ๊ป˜ ์••์ถ• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ( TwoInt32Wrappersํฌ๊ธฐ๋Š” 8).
  • ์ฐธ์กฐ ์œ ํ˜• ํ•„๋“œ๊ฐ€ ์žˆ์–ด๋„ CLR์€ ์—ฌ์ „ํžˆ intํ•„๋“œ๋ฅผ ํ•จ๊ป˜ ์••์ถ• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ( RefAndTwoInt32sํฌ๊ธฐ๋Š” 16).
  • ๋‘ ๊ฐ€์ง€๋ฅผ ๊ฒฐํ•ฉํ•˜๋ฉด ๊ฐ Int32Wrapperํ•„๋“œ๊ฐ€ 8 ๋ฐ”์ดํŠธ๋กœ ์ฑ„์›Œ์ง€๊ฑฐ๋‚˜ ์ •๋ ฌ ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ( RefAndTwoInt32Wrappersํฌ๊ธฐ๋Š” 24์ž…๋‹ˆ๋‹ค.)
  • ๋””๋ฒ„๊ฑฐ์—์„œ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด (ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฆด๋ฆฌ์Šค ๋นŒ๋“œ) ํฌ๊ธฐ๊ฐ€ 12๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋ช‡ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์‹คํ—˜์—์„œ๋„ ๋น„์Šทํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.

  • ๊ฐ’ ์œ ํ˜• ํ•„๋“œ ๋’ค์— ์ฐธ์กฐ ์œ ํ˜• ํ•„๋“œ๋ฅผ ๋‘๋Š” ๊ฒƒ์€ ๋„์›€์ด๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • object๋Œ€์‹  ์‚ฌ์šฉ ํ•˜๋Š” string๊ฒƒ์€ ๋„์›€ ์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ( โ€œ๋ชจ๋“  ์ฐธ์กฐ ์œ ํ˜•โ€์ผ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ).
  • ์ฐธ์กฐ ์ฃผ์œ„์˜ โ€œ๋ž˜ํผโ€๋กœ ๋‹ค๋ฅธ ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋„์›€์ด๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ฐธ์กฐ ์ฃผ์œ„์˜ ๋ž˜ํผ๋กœ ์ผ๋ฐ˜ ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋„์›€์ด๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ํ•„๋“œ๋ฅผ ๊ณ„์† ์ถ”๊ฐ€ํ•˜๋ฉด (๋‹จ์ˆœ์„ฑ์„ ์œ„ํ•ด ์Œ์œผ๋กœ) intํ•„๋“œ๋Š” ์—ฌ์ „ํžˆ 4 ๋ฐ”์ดํŠธ๋กœ Int32Wrapper๊ณ„์‚ฐ ๋˜๊ณ  ํ•„๋“œ๋Š” 8 ๋ฐ”์ดํŠธ๋กœ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
  • [StructLayout(LayoutKind.Sequential, Pack = 4)]์‹œ์•ผ์—์žˆ๋Š” ๋ชจ๋“  ๊ตฌ์กฐ์ฒด์— ์ถ”๊ฐ€ํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€ ์ด์— ๋Œ€ํ•œ ์„ค๋ช… (์ด์ƒ์ ์œผ๋กœ๋Š” ์ฐธ์กฐ ๋ฌธ์„œ ํฌํ•จ)์ด ์žˆ๊ฑฐ๋‚˜ ์ƒ์ˆ˜ ํ•„๋“œ ์˜คํ”„์…‹ ์„ ์ง€์ • ํ•˜์ง€ ์•Š๊ณ  ํ•„๋“œ๋ฅผ ์••์ถ•ํ•˜๊ณ  ์‹ถ๋‹ค๋Š” CLR์— ๋Œ€ํ•œ ํžŒํŠธ๋ฅผ ์–ป์„ ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ œ์•ˆ์ด ์žˆ์Šต๋‹ˆ๊นŒ?



๋‹ต๋ณ€

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋ฒ„๊ทธ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ž๋™ ๋ ˆ์ด์•„์›ƒ์˜ ๋ถ€์ž‘์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. 64 ๋น„ํŠธ ๋ชจ๋“œ์—์„œ 8 ๋ฐ”์ดํŠธ์˜ ๋ฐฐ์ˆ˜ ์ธ ์ฃผ์†Œ์— ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ•„๋“œ๋ฅผ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. [StructLayout(LayoutKind.Sequential)]์†์„ฑ ์„ ๋ช…์‹œ ์ ์œผ๋กœ ์ ์šฉํ•œ ๊ฒฝ์šฐ์—๋„ ๋ฐœ์ƒ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ผ์–ด๋‚˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์กฐ์ฒด ๋ฉค๋ฒ„๋ฅผ ๊ณต๊ฐœํ•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    var test = new RefAndTwoInt32Wrappers();
    test.text = "adsf";
    test.x.x = 0x11111111;
    test.y.x = 0x22222222;
    Console.ReadLine();      // <=== Breakpoint here

์ค‘๋‹จ ์ ์— ๋„๋‹ฌํ•˜๋ฉด Debug + Windows + Memory + Memory 1์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 4 ๋ฐ”์ดํŠธ ์ •์ˆ˜๋กœ ์ „ํ™˜ &testํ•˜๊ณ  Address ํ•„๋“œ์— ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 0x000000E928B5DE98  0ed750e0 000000e9 11111111 00000000 22222222 00000000 

0xe90ed750e0๋‚ด ์ปดํ“จํ„ฐ์˜ ๋ฌธ์ž์—ด ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค (๋‹น์‹ ์˜ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค). ์‰ฝ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹คInt32Wrappersํฌ๊ธฐ๋ฅผ 24 ๋ฐ”์ดํŠธ๋กœ ๋ฐ”๊พธ๋Š” ์ถ”๊ฐ€ 4 ๋ฐ”์ดํŠธ์˜ ํŒจ๋”ฉ์œผ๋กœ์„ . ๊ตฌ์กฐ์ฒด๋กœ ๋Œ์•„๊ฐ€์„œ ๋ฌธ์ž์—ด์„ ๋งˆ์ง€๋ง‰์— ๋„ฃ์œผ์‹ญ์‹œ์˜ค. ๋ฐ˜๋ณตํ•˜๋ฉด ๋ฌธ์ž์—ด ํฌ์ธํ„ฐ๊ฐ€ ์—ฌ์ „ํžˆ ์ฒซ ๋ฒˆ์งธ ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค . ์œ„๋ฐ˜ LayoutKind.Sequential, ๋‹น์‹ ์€ LayoutKind.Auto.

๋งˆ์ดํฌ๋กœ ์†Œํ”„ํŠธ๊ฐ€์ด ๋ฌธ์ œ๋ฅผ ๊ณ ์น˜๋„๋ก ์„ค๋“ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ค์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ์˜ค๋žซ๋™์•ˆ ์ด๋Ÿฐ ์‹์œผ๋กœ ์ž‘๋™ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๋ณ€ํ™”๋„ ๊นจ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฌด์–ธ๊ฐ€๋ฅผ ๋œจ๋ฆฌ๊ฒŒ ๊ฒƒ ์ž…๋‹ˆ๋‹ค. CLR [StructLayout]์€ struct์˜ ๊ด€๋ฆฌ ๋ฒ„์ „ ์„ ์กด์ค‘ ํ•˜๊ณ  blittable๋กœ ๋งŒ๋“ค ๋ ค๊ณ  ์‹œ๋„ ํ•  ๋ฟ์ด๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ๋น ๋ฅด๊ฒŒ ํฌ๊ธฐํ•ฉ๋‹ˆ๋‹ค. DateTime์„ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ๊ตฌ์กฐ์ฒด์— ๋Œ€ํ•ด ์œ ๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด๋ฅผ ๋งˆ์ƒฌ๋ง ํ•  ๋•Œ๋งŒ ์ง„์ •ํ•œ LayoutKind ๋ณด์žฅ์„๋ฐ›์Šต๋‹ˆ๋‹ค. ๋งˆ์ƒฌ๋ง ๋œ ๋ฒ„์ „์€ ํ™•์‹คํžˆ 16 ๋ฐ”์ดํŠธ Marshal.SizeOf()์ž…๋‹ˆ๋‹ค.

LayoutKind.Explicit๋‹น์‹ ์ด ๋“ฃ๊ณ  ์‹ถ์—ˆ๋˜ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๊ทธ๊ฒƒ์„ ๊ณ ์ณ ์‚ฌ์šฉ ํ•˜์‹ญ์‹œ์˜ค.


๋‹ต๋ณ€

EDIT2

struct RefAndTwoInt32Wrappers
{
    public int x;
    public string s;
}

์ด ์ฝ”๋“œ๋Š” 8 ๋ฐ”์ดํŠธ๋กœ ์ •๋ ฌ๋˜๋ฏ€๋กœ ๊ตฌ์กฐ์ฒด๋Š” 16 ๋ฐ”์ดํŠธ๋ฅผ ๊ฐ–๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ๋น„๊ตํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

struct RefAndTwoInt32Wrappers
{
    public int x,y;
    public string s;
}

4 ๋ฐ”์ดํŠธ๋กœ ์ •๋ ฌ๋˜๋ฏ€๋กœ์ด ๊ตฌ์กฐ์ฒด๋„ 16 ๋ฐ”์ดํŠธ๋ฅผ ๊ฐ–๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์—ฌ๊ธฐ์˜ ์ด๋ก ์  ๊ทผ๊ฑฐ๋Š” CLR์˜ ๊ตฌ์กฐ์ฒด ๊ฒฐํ•ฉ์ด ๊ฐ€์žฅ ๋งŽ์ด ์ •๋ ฌ ๋œ ํ•„๋“œ์˜ ์ˆ˜์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. clases๋Š” ๋ถ„๋ช…ํžˆ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ 8 ๋ฐ”์ดํŠธ ์ •๋ ฌ ์ƒํƒœ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ชจ๋“  ๊ฒƒ์„ ๊ฒฐํ•ฉํ•˜๊ณ  ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด :

struct RefAndTwoInt32Wrappers
{
    public int x,y;
    public Int32Wrapper z;
    public string s;
}

24 ๋ฐ”์ดํŠธ {x, y}๋Š” ๊ฐ๊ฐ 4 ๋ฐ”์ดํŠธ, {z, s}๋Š” 8 ๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด์— ref ์œ ํ˜•์„ ๋„์ž…ํ•˜๋ฉด CLR์€ ํ•ญ์ƒ ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์กฐ์ฒด๋ฅผ ํด๋ž˜์Šค ์ •๋ ฌ๊ณผ ์ผ์น˜ํ•˜๋„๋ก ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.

struct RefAndTwoInt32Wrappers
{
    public Int32Wrapper z;
    public long l;
    public int x,y;
}

Int32Wrapper๋Š” ๊ธธ์ด์™€ ๋™์ผํ•˜๊ฒŒ ์ •๋ ฌ๋˜๋ฏ€๋กœ์ด ์ฝ”๋“œ๋Š” 24 ๋ฐ”์ดํŠธ๋ฅผ ๊ฐ–๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์กฐ์ฒด ๋ž˜ํผ๋Š” ํ•ญ์ƒ ๊ตฌ์กฐ์—์„œ ๊ฐ€์žฅ ๋†’์€ / ๊ฐ€์žฅ ์ •๋ ฌ ๋œ ํ•„๋“œ ๋˜๋Š” ์ž์ฒด ๋‚ด๋ถ€ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํ•„๋“œ์— ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ 8 ๋ฐ”์ดํŠธ ์ •๋ ฌ ๋œ ์ฐธ์กฐ ๋ฌธ์ž์—ด์˜ ๊ฒฝ์šฐ ๊ตฌ์กฐ์ฒด ๋ž˜ํผ๊ฐ€ ์ด์— ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค.

๊ตฌ์กฐ์ฒด ๋‚ด๋ถ€์˜ ์ตœ์ข… ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์กฐ์ฒด ํ•„๋“œ๋Š” ํ•ญ์ƒ ๊ตฌ์กฐ์ฒด์—์„œ ๊ฐ€์žฅ ๋†’๊ฒŒ ์ •๋ ฌ ๋œ ์ธ์Šคํ„ด์Šค ํ•„๋“œ์— ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ์ด๊ฒƒ์ด ๋ฒ„๊ทธ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์ฆ๊ฑฐ๊ฐ€ ์—†์œผ๋ฉด ์ด๊ฒƒ์ด ์˜์‹์ ์ธ ๊ฒฐ์ •์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‚ด ์˜๊ฒฌ์„ ๊ณ ์ˆ˜ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.


ํŽธ์ง‘ํ•˜๋‹ค

ํฌ๊ธฐ๋Š” ์‹ค์ œ๋กœ ํž™์— ํ• ๋‹น ๋œ ๊ฒฝ์šฐ์—๋งŒ ์ •ํ™•ํ•˜์ง€๋งŒ ๊ตฌ์กฐ์ฒด ์ž์ฒด์˜ ํฌ๊ธฐ๋Š” ๋” ์ž‘์Šต๋‹ˆ๋‹ค (ํ•„๋“œ์˜ ์ •ํ™•ํ•œ ํฌ๊ธฐ). ์ถ”๊ฐ€ ๋ถ„์„์„ ํ†ตํ•ด ์ด๊ฒƒ์ด CLR ์ฝ”๋“œ์˜ ๋ฒ„๊ทธ ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ฆ๊ฑฐ๋กœ ๋ฐฑ์—…ํ•ด์•ผ ํ•จ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” cli ์ฝ”๋“œ๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ  ์œ ์šฉํ•œ ๊ฒƒ์ด ๋ฐœ๊ฒฌ๋˜๋ฉด ์ถ”๊ฐ€ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฒŒ์‹œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.


์ด๊ฒƒ์€ .NET mem ํ• ๋‹น ์ž์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ •๋ ฌ ์ „๋žต์ž…๋‹ˆ๋‹ค.

public static RefAndTwoInt32s[] test = new RefAndTwoInt32s[1];

static void Main()
{
    test[0].text = "a";
    test[0].x = 1;
    test[0].x = 1;

    Console.ReadKey();
}

x64์—์„œ .net40์œผ๋กœ ์ปดํŒŒ์ผ ๋œ์ด ์ฝ”๋“œ๋Š” WinDbg์—์„œ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ํž™์—์„œ ์œ ํ˜•์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    0:004> !dumpheap -type Ref
       Address               MT     Size
0000000003e72c78 000007fe61e8fb58       56
0000000003e72d08 000007fe039d3b78       40

Statistics:
              MT    Count    TotalSize Class Name
000007fe039d3b78        1           40 RefAndTwoInt32s[]
000007fe61e8fb58        1           56 System.Reflection.RuntimeAssembly
Total 2 objects

์ผ๋‹จ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ ์ฃผ์†Œ ์•„๋ž˜์— ๋ฌด์—‡์ด ์žˆ๋Š”์ง€ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    0:004> !do 0000000003e72d08
Name:        RefAndTwoInt32s[]
MethodTable: 000007fe039d3b78
EEClass:     000007fe039d3ad0
Size:        40(0x28) bytes
Array:       Rank 1, Number of elements 1, Type VALUETYPE
Fields:
None

์ด๊ฒƒ์ด ValueType์ด๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑ ํ•œ ๊ฒƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐฐ์—ด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด์—์žˆ๋Š” ๋‹จ์ผ ์š”์†Œ์˜ ValueType def๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•ฉ๋‹ˆ๋‹ค.

    0:004> !dumparray -details 0000000003e72d08
Name:        RefAndTwoInt32s[]
MethodTable: 000007fe039d3b78
EEClass:     000007fe039d3ad0
Size:        40(0x28) bytes
Array:       Rank 1, Number of elements 1, Type VALUETYPE
Element Methodtable: 000007fe039d3a58
[0] 0000000003e72d18
    Name:        RefAndTwoInt32s
    MethodTable: 000007fe039d3a58
    EEClass:     000007fe03ae2338
    Size:        32(0x20) bytes
    File:        C:\ConsoleApplication8\bin\Release\ConsoleApplication8.exe
    Fields:
                      MT    Field   Offset                 Type VT     Attr            Value Name
        000007fe61e8c358  4000006        0            System.String      0     instance     0000000003e72d30     text
        000007fe61e8f108  4000007        8             System.Int32      1     instance                    1     x
        000007fe61e8f108  4000008        c             System.Int32      1     instance                    0     y

16 ๋ฐ”์ดํŠธ๊ฐ€ ํŒจ๋”ฉ ์šฉ์œผ๋กœ ์˜ˆ์•ฝ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๊ตฌ์กฐ๋Š” ์‹ค์ œ๋กœ 32 ๋ฐ”์ดํŠธ์ด๋ฏ€๋กœ ์‹ค์ œ๋กœ ๋ชจ๋“  ๊ตฌ์กฐ๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ์ตœ์†Œ 16 ๋ฐ”์ดํŠธ ํฌ๊ธฐ์ž…๋‹ˆ๋‹ค.

int์™€ ๋ฌธ์ž์—ด ์ฐธ์กฐ์—์„œ 16 ๋ฐ”์ดํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด 0000000003e72d18 + 8 ๋ฐ”์ดํŠธ EE / ํŒจ๋”ฉ์ด๋ฉ๋‹ˆ๋‹ค. 0000000003e72d30์ด๋˜๊ณ  ์ด๊ฒƒ์€ ๋ฌธ์ž์—ด ์ฐธ์กฐ์˜ ์‹œ์ž‘ ์ง€์ ์ด๋ฉฐ ๋ชจ๋“  ์ฐธ์กฐ๋Š” ์ฒซ ๋ฒˆ์งธ ์‹ค์ œ ๋ฐ์ดํ„ฐ ํ•„๋“œ์—์„œ 8 ๋ฐ”์ดํŠธ๊ฐ€ ์ฑ„์›Œ ์ง€๋ฏ€๋กœ ์ด๊ฒƒ์€์ด ๊ตฌ์กฐ์˜ 32 ๋ฐ”์ดํŠธ๋ฅผ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด์ด ์‹ค์ œ๋กœ ๊ทธ๋ ‡๊ฒŒ ์ฑ„์›Œ์ ธ ์žˆ๋Š”์ง€ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

0:004> !do 0000000003e72d30
Name:        System.String
MethodTable: 000007fe61e8c358
EEClass:     000007fe617f3720
Size:        28(0x1c) bytes
File:        C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      a
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fe61e8f108  40000aa        8         System.Int32  1 instance                1 m_stringLength
000007fe61e8d640  40000ab        c          System.Char  1 instance               61 m_firstChar
000007fe61e8c358  40000ac       18        System.String  0   shared           static Empty
                                 >> Domain:Value  0000000001577e90:NotInit  <<

์ด์ œ ์œ„์˜ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public static RefAndTwoInt32Wrappers[] test = new RefAndTwoInt32Wrappers[1];

static void Main()
{
    test[0].text = "a";
    test[0].x.x = 1;
    test[0].y.x = 1;

    Console.ReadKey();
}

0:004> !dumpheap -type Ref
     Address               MT     Size
0000000003c22c78 000007fe61e8fb58       56
0000000003c22d08 000007fe039d3c00       48

Statistics:
              MT    Count    TotalSize Class Name
000007fe039d3c00        1           48 RefAndTwoInt32Wrappers[]
000007fe61e8fb58        1           56 System.Reflection.RuntimeAssembly
Total 2 objects

์ด์ œ ๊ตฌ์กฐ์ฒด๋Š” 48 ๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค.

0:004> !dumparray -details 0000000003c22d08
Name:        RefAndTwoInt32Wrappers[]
MethodTable: 000007fe039d3c00
EEClass:     000007fe039d3b58
Size:        48(0x30) bytes
Array:       Rank 1, Number of elements 1, Type VALUETYPE
Element Methodtable: 000007fe039d3ae0
[0] 0000000003c22d18
    Name:        RefAndTwoInt32Wrappers
    MethodTable: 000007fe039d3ae0
    EEClass:     000007fe03ae2338
    Size:        40(0x28) bytes
    File:        C:\ConsoleApplication8\bin\Release\ConsoleApplication8.exe
    Fields:
                      MT    Field   Offset                 Type VT     Attr            Value Name
        000007fe61e8c358  4000009        0            System.String      0     instance     0000000003c22d38     text
        000007fe039d3a20  400000a        8             Int32Wrapper      1     instance     0000000003c22d20     x
        000007fe039d3a20  400000b       10             Int32Wrapper      1     instance     0000000003c22d28     y

์—ฌ๊ธฐ์„œ ์ƒํ™ฉ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. 0000000003c22d18 + 8 ๋ฐ”์ดํŠธ์˜ ๋ฌธ์ž์—ด ์ฐธ์กฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๊ฐ’์ด ์‹ค์ œ๋กœ ์šฐ๋ฆฌ๊ฐ€์žˆ๋Š” ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฒซ ๋ฒˆ์งธ Int ๋ž˜ํผ์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์—์„œ ๋๋‚ฉ๋‹ˆ๋‹ค.

์ด์ œ ๊ฐ ๊ฐ’์ด ๊ฐ์ฒด ์ฐธ์กฐ์ž„์„ ๋‹ค์‹œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 0000000003c22d20์„ ์‚ดํŽด๋ณด๋ฉด์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

0:004> !do 0000000003c22d20
<Note: this object has an invalid CLASS field>
Invalid object

์‹ค์ œ๋กœ ๊ทธ๊ฒƒ์ด obj ๋˜๋Š” vt์ด๋ฉด ์ฃผ์†Œ๊ฐ€ ์šฐ๋ฆฌ์—๊ฒŒ ์•„๋ฌด๊ฒƒ๋„ ์•Œ๋ ค์ฃผ์ง€ ์•Š๋Š” ๊ตฌ์กฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ •ํ™•ํ•ฉ๋‹ˆ๋‹ค.

0:004> !dumpvc 000007fe039d3a20   0000000003c22d20
Name:        Int32Wrapper
MethodTable: 000007fe039d3a20
EEClass:     000007fe03ae23c8
Size:        24(0x18) bytes
File:        C:\ConsoleApplication8\bin\Release\ConsoleApplication8.exe
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fe61e8f108  4000001        0         System.Int32  1 instance                1 x

๋”ฐ๋ผ์„œ ์‹ค์ œ๋กœ ์ด๊ฒƒ์€ ์ด๋ฒˆ์— 8 ๋ฐ”์ดํŠธ ์ •๋ ฌ๋˜๋Š” Union ์œ ํ˜•๊ณผ ๋” ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค (๋ชจ๋“  ํŒจ๋”ฉ์€ ๋ถ€๋ชจ ๊ตฌ์กฐ์ฒด์™€ ์ •๋ ฌ ๋จ). ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด 20 ๋ฐ”์ดํŠธ๋กœ ๋๋‚  ๊ฒƒ์ด๊ณ  ๊ทธ๊ฒƒ์€ ์ตœ์ ์ด ์•„๋‹ˆ๋ฏ€๋กœ mem ํ• ๋‹น์ž๋Š” ๊ฒฐ์ฝ” ๊ทธ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ˆ˜ํ•™์„ํ•˜๋ฉด ๊ตฌ์กฐ์ฒด์˜ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ๋กœ 40 ๋ฐ”์ดํŠธ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ข€ ๋” ๋ณด์ˆ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ตฌ์กฐ์ฒด ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์กฐ์ฒด ํ˜•์‹์œผ๋กœ ์••์ถ•ํ•˜์ง€ ๋ง๊ณ  ๋Œ€์‹  ๊ฐ„๋‹จํ•œ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ํž™ (์˜ˆ : VirtualAllocEx)์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๊ณ ์œ  ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก์ด ์ œ๊ณต๋˜๊ณ  ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ด€๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋งˆ์ง€๋ง‰ ์งˆ๋ฌธ์€ ์™œ ๊ฐ‘์ž๊ธฐ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋Ÿฐ ๋ ˆ์ด์•„์›ƒ์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š”์ง€์ž…๋‹ˆ๋‹ค. int [] ์ฆ๋ถ„์˜ ์ง€ ํ‹ฐ๋“œ ์ฝ”๋“œ์™€ ์„ฑ๋Šฅ์„ struct []์™€ ์นด์šดํ„ฐ ํ•„๋“œ ์ฆ๋ถ„๊ณผ ๋น„๊ตํ•˜๋ฉด ๋‘ ๋ฒˆ์งธ๋Š” ์œ ๋‹ˆ์˜จ์ด๋˜๋Š” 8 ๋ฐ”์ดํŠธ ์ •๋ ฌ ์ฃผ์†Œ๋ฅผ ์ƒ์„ฑํ•˜์ง€๋งŒ ์ง€ํŒ…ํ•˜๋ฉด ๋” ์ตœ์ ํ™” ๋œ ์–ด์…ˆ๋ธ”๋ฆฌ ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค (๋‹จ์ผ LEA ๋Œ€ ๋‹ค์ค‘ MOV). ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์— ์„ค๋ช… ๋œ ๊ฒฝ์šฐ ์„ฑ๋Šฅ์ด ์‹ค์ œ๋กœ ๋” ๋‚˜๋น ์งˆ ๊ฒƒ์ด๋ฏ€๋กœ ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜์žˆ๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ํ˜•์‹์ด๋ฏ€๋กœ ๊ธฐ๋ณธ CLR ๊ตฌํ˜„๊ณผ ์ผ์น˜ํ•˜๋ฏ€๋กœ ์‹œ์ž‘ ์ฃผ์†Œ ๋Œ€์‹  ์‹œ์ž‘ ์ฃผ์†Œ๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. value (๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—) ๊ทธ๋ฆฌ๊ณ  ๊ฑฐ๊ธฐ์—์„œ ๊ตฌ์กฐ์ฒด ํŒจ๋”ฉ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋” ํฐ ๋ฐ”์ดํŠธ ํฌ๊ธฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.


๋‹ต๋ณ€

์š”์•ฝ์€ ์•„๋งˆ๋„ ์œ„์˜ @Hans Passant์˜ ๋‹ต๋ณ€์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. Layout Sequential์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


์ผ๋ถ€ ํ…Œ์ŠคํŠธ :

๊ทธ๊ฒƒ์€ ํ™•์‹คํžˆ 64 ๋น„ํŠธ์—๋งŒ ์žˆ๊ณ  ๊ฐ์ฒด ์ฐธ์กฐ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ โ€œ๋…โ€์‹œํ‚ต๋‹ˆ๋‹ค. 32 ๋น„ํŠธ๋Š” ๋‹น์‹ ์ด ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฒƒ์„ํ•ฉ๋‹ˆ๋‹ค :

Environment: CLR 4.0.30319.34209 on Microsoft Windows NT 6.2.9200.0 (32 bit)
ConsoleApplication1.Int32Wrapper: 4
ConsoleApplication1.TwoInt32s: 8
ConsoleApplication1.TwoInt32Wrappers: 8
ConsoleApplication1.ThreeInt32Wrappers: 12
ConsoleApplication1.Ref: 4
ConsoleApplication1.RefAndTwoInt32s: 12
ConsoleApplication1.RefAndTwoInt32Wrappers: 12
ConsoleApplication1.RefAndThreeInt32s: 16
ConsoleApplication1.RefAndThreeInt32Wrappers: 16

๊ฐ์ฒด ์ฐธ์กฐ๊ฐ€ ์ถ”๊ฐ€ ๋˜ ์ž๋งˆ์ž ๋ชจ๋“  ๊ตฌ์กฐ์ฒด๋Š” 4 ๋ฐ”์ดํŠธ ํฌ๊ธฐ๊ฐ€ ์•„๋‹Œ 8 ๋ฐ”์ดํŠธ๋กœ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ํ™•์žฅ :

Environment: CLR 4.0.30319.34209 on Microsoft Windows NT 6.2.9200.0 (64 bit)
ConsoleApplication1.Int32Wrapper: 4
ConsoleApplication1.TwoInt32s: 8
ConsoleApplication1.TwoInt32Wrappers: 8
ConsoleApplication1.ThreeInt32Wrappers: 12
ConsoleApplication1.Ref: 8
ConsoleApplication1.RefAndTwoInt32s: 16
ConsoleApplication1.RefAndTwoInt32sSequential: 16
ConsoleApplication1.RefAndTwoInt32Wrappers: 24
ConsoleApplication1.RefAndThreeInt32s: 24
ConsoleApplication1.RefAndThreeInt32Wrappers: 32
ConsoleApplication1.RefAndFourInt32s: 24
ConsoleApplication1.RefAndFourInt32Wrappers: 40

์ฐธ์กฐ๊ฐ€ ์ถ”๊ฐ€ ๋˜ ์ž๋งˆ์ž ๋ชจ๋“  Int32Wrapper๊ฐ€ 8 ๋ฐ”์ดํŠธ๊ฐ€๋˜๋ฏ€๋กœ ๋‹จ์ˆœํ•œ ์ •๋ ฌ์ด ์•„๋‹™๋‹ˆ๋‹ค. LoH ํ• ๋‹น์ด ๋‹ค๋ฅด๊ฒŒ ์ •๋ ฌ ๋œ ๊ฒฝ์šฐ ๋ฐฐ์—ด ํ• ๋‹น์„ ์ค„์˜€์Šต๋‹ˆ๋‹ค.


๋‹ต๋ณ€

๋ฏน์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ๋ณด์œ ํ•œ ์œ ํ˜•์—์„œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์œ ํ˜•์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

struct RefAndTwoInt32Wrappers2
{
    string text;
    TwoInt32Wrappers z;
}

ํ”„๋กœ๊ทธ๋žจ์€ ๋‹ค์Œ์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

RefAndTwoInt32Wrappers2: 16

๋”ฐ๋ผ์„œ TwoInt32Wrappers๊ตฌ์กฐ์ฒด๊ฐ€ ์ƒˆ RefAndTwoInt32Wrappers2๊ตฌ์กฐ์ฒด ์—์„œ ์ œ๋Œ€๋กœ ์ •๋ ฌ ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค .


๋‹ต๋ณ€


์ด ๊ธ€์€ C# ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๋ถ„๋ฅ˜๋˜์—ˆ๊ณ  ๋‹˜์— ์˜ํ•ด ์— ์ž‘์„ฑ๋์Šต๋‹ˆ๋‹ค.