Уничтожить объект структуры в C #?

Попробуем этот код:

    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;
self.navigationController.view.center = CGPointMake(([UIScreen mainScreen].bounds.size.width/2), [UIScreen mainScreen].bounds.size.height/2);
CGFloat angle = 90 * M_PI / 180;
self.navigationController.view.transform = CGAffineTransformMakeRotation(angle);
self.navigationController.view.bounds = CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.height , [UIScreen mainScreen].bounds.size.width);
21
задан kvb 27 January 2010 в 19:07
поделиться

7 ответов

Для начала, независимо от того, зависит ли они в стеке или части кучи, зависит от того, в каком контексте они являются частью - если они в пределах ссылочного типа, они будут на куча в любом случае. (Вы должны учитывать, насколько вы действительно заботитесь о стеке / кучи, разделяете все равно - как написал Эрик ЛППППП, это в значительной степени реализации деталей .)

Тем не менее, в основном, в основном память типов. Восстановлено - поэтому, когда стек выскочит, вы возвращаете из способа, что «восстанавливает» весь стек кадра. Аналогичным образом, если значение типа значения на самом деле является частью объекта, то память восстанавливается, когда этот объект является собранным мусором.

Краткий ответ - это то, что вам не нужно беспокоиться о нем :) (это предполагает, что у вас нет ничего других , чем память, которым нужно беспокоиться, конечно - если у вас есть Структы со ссылками на родные ручки, которые нуждаются в выпуске, это несколько разный сценарий.)

31
ответ дан 29 November 2019 в 06:34
поделиться

также хотел бы добавить этот стек на уровне потока, а куча на уровне домена приложения.

Итак, когда нить заканчивается, она будет отмена память стека, используемой этой определенной нитью.

0
ответ дан 29 November 2019 в 06:34
поделиться

Типы значений будут оформляться, когда кадра стека удаляется после его выполнения, я бы предположил

0
ответ дан 29 November 2019 в 06:34
поделиться

Я боюсь, что вы должны прибегать к использованию P / Invoke. Есть пример, как это сделать в pinvoke.net (см. Нижнюю часть страницы):

Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenSessionId , TokenInformation , TokenInfLength , out TokenInfLength );

Обратите внимание, что я изменил пример, изменяя только одну строку, я заменил Token_information_Class. Tokenuser с TOKEN_INFORMATION_CLASS.TokensionId , который именно то, что вам нужно.

Надеюсь, это поможет.

Обновление: вот работа (по крайней мере на моем машине) код:

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace LinqTest
{
    public class ClsLookupAccountName
    {
        public const uint SE_GROUP_LOGON_ID = 0xC0000000; // from winnt.h
        public const int TokenGroups = 2; // from TOKEN_INFORMATION_CLASS

        enum TOKEN_INFORMATION_CLASS
        {
            TokenUser = 1,
            TokenGroups,
            TokenPrivileges,
            TokenOwner,
            TokenPrimaryGroup,
            TokenDefaultDacl,
            TokenSource,
            TokenType,
            TokenImpersonationLevel,
            TokenStatistics,
            TokenRestrictedSids,
            TokenSessionId,
            TokenGroupsAndPrivileges,
            TokenSessionReference,
            TokenSandBoxInert,
            TokenAuditPolicy,
            TokenOrigin
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SID_AND_ATTRIBUTES
        {
            public IntPtr Sid;
            public uint Attributes;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_GROUPS
        {
            public int GroupCount;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
            public SID_AND_ATTRIBUTES[] Groups;
        };

        // Using IntPtr for pSID instead of Byte[]
        [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid);

        [DllImport("kernel32.dll")]
        static extern IntPtr LocalFree(IntPtr hMem);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool GetTokenInformation(
            IntPtr TokenHandle,
            TOKEN_INFORMATION_CLASS TokenInformationClass,
            IntPtr TokenInformation,
            int TokenInformationLength,
            out int ReturnLength);

        public static string GetLogonId()
        {
            int TokenInfLength = 0;
            // first call gets lenght of TokenInformation
            bool Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, TokenInfLength, out TokenInfLength);
            IntPtr TokenInformation = Marshal.AllocHGlobal(TokenInfLength);
            Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, TokenInformation, TokenInfLength, out TokenInfLength);

            if (!Result)
            {
                Marshal.FreeHGlobal(TokenInformation);
                return string.Empty;
            }

            string retVal = string.Empty;
            TOKEN_GROUPS groups = (TOKEN_GROUPS)Marshal.PtrToStructure(TokenInformation, typeof(TOKEN_GROUPS));
            int sidAndAttrSize = Marshal.SizeOf(new SID_AND_ATTRIBUTES());
            for (int i = 0; i < groups.GroupCount; i++)
            {
                SID_AND_ATTRIBUTES sidAndAttributes = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(
                    new IntPtr(TokenInformation.ToInt64() + i * sidAndAttrSize + IntPtr.Size), typeof(SID_AND_ATTRIBUTES));
                if ((sidAndAttributes.Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
                {
                    IntPtr pstr = IntPtr.Zero;
                    ConvertSidToStringSid(sidAndAttributes.Sid, out pstr);
                    retVal = Marshal.PtrToStringAuto(pstr);
                    LocalFree(pstr);
                    break;
                }
            }

            Marshal.FreeHGlobal(TokenInformation);
            return retVal;
        }
    }
}

N.B. Я проверил его на моем машине X64, поэтому, пожалуйста, уделяйте пристальное внимание Tokeninformation.toint64 () Кусок кода, может быть, вы должны заменить его с помощью Tokeninformation.toint32 ()

-121 -3367017-

Тип значения на стеке удаляется из стека, когда он выходит из неисправности.

3
ответ дан 29 November 2019 в 06:34
поделиться

Слишком много глаголов, используемых в этом вопросе, вроде уничтоженных, восстановленных, освобожденных, удаленных. Это плохо соответствует тому, что на самом деле происходит. Локальная переменная просто перестает быть, норвежский стиль попугай .

Способ имеет одну точку записи, первое, что происходит, состоит в том, что указатель стека CPU отрегулирован. Создание «кадров стека», места для хранения локальных переменных. CLR гарантирует, что это пространство инициализируется до 0, не иначе функция, которую вы используете сильно в C # из-за определенного правила назначения.

Способ имеет одну точку выхода, даже если вы код метода пересыпают с несколькими возвратами . В этот момент указатель стека просто восстанавливается до его первоначального значения. По сути, «забывает», что местные переменные, где когда-либо там. Их ценности не «ломаны» никоим образом, байты все еще там. Но они не будут длиться долго, следующий звонок в вашей программе собирается перезаписать их снова. Правило ноль инициализации CLR гарантирует, что вы никогда не можете наблюдать за этими старыми значениями, это было бы неуверенно.

Очень быстро, не требует не более одного процессора цикла. Видимый побочный эффект этого поведения в языке C # заключается в том, что типы значения не могут иметь финализатор. Обеспечение дополнительной работы не должно быть сделано.

7
ответ дан 29 November 2019 в 06:34
поделиться

Типы значений разрушаются, как только они выйдут из охвата.

3
ответ дан 29 November 2019 в 06:34
поделиться

Я немного запутался в том, что в C # только ссылочные типы получают сборки мусора.

Это не факт. Или, скорее, правда или ложность этого утверждения зависит от того, что вы подразумеваете под «получение мусора». Коллектор мусора, безусловно, смотрит на типы значений при сборе; Эти типы значений могут быть живы и удерживать ссылочный тип:

struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M(); 

, когда сборщик мусора работает, безусловно, смотрит на S, потому что ему нужно определить, что S.STR еще жив.

Мое предложение: уточнить точно , что вы подразумеваете под глаголом », получает сборщик мусора».

GC выбирает только ссылочные типы для распределения памяти.

Опять же, это не факт. Предположим, у вас есть экземпляр

class C { int x; }

, память для целого числа будет на сборной мусоре, и поэтому восстановлена ​​сборщиком мусора, когда экземпляр C становится нерешенным.

Почему вы верите, что ложь, что только память опорных типов выделена сборщиком мусора? Правильное утверждение состоит в том, что память, которая была выделена , выделена соленым сборщиком мусора . Складки мусора , который, я думаю, имеет смысл. GC выделил его, чтобы он отвечает за его уборку.

Так что происходит с типовыми типами, так как они также занимают память на стеке?

Ничего вообще не происходит с ними. С ними не должно случиться. Стек составляет миллион байтов. Размер стека определяется, когда нить запускается; Он начинается с миллиона байтов, и он остается миллион байтов на протяжении всего выполнения нити. Память на стеке не создается и не уничтожена; Только его содержимое изменено.

19
ответ дан 29 November 2019 в 06:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: