c# куча - Распределение памяти: стек против кучи?




4 Answers

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

class MyClass
{
    int myInt = 0;

    string myString = "Something";

    void Foo(int x, int y) {
       int rv = x + y + myInt;
       myInt = 2^rv;
    }
}

rv , x , y все будут в стеке. myInt находится где-то в куче (и должен быть доступ через this указатель).

очередь динамическая

Я путаюсь с основами распределения памяти между Stack vs Heap . В соответствии с стандартным определением (все, что все говорят) все типы значений будут распределены по стекам, а ссылочные типы войдут в кучу .

Теперь рассмотрим следующий пример:

class MyClass
{
    int myInt = 0;    
    string myString = "Something";
}

class Program
{
    static void Main(string[] args)
    {
       MyClass m = new MyClass();
    }
}

Теперь, как распределение памяти произойдет в c #? Будет ли объект MyClass (т. MyClass m ) полностью выделен куче? То есть, int myInt и string myString будут идти в кучу?

Или объект будет разделен на две части и будет выделен обоим местам памяти, которые представляют собой стек и кучу?




«Все типы VALUE будут выделены для Stack» очень, очень неправильно; переменные структуры могут жить в стеке, как переменные метода. Тем не менее поля с типом живут с этим типом . Если тип объявления поля является классом, значения находятся в куче как часть этого объекта. Если тип объявления поля является структурой, поля являются частью этой структуры, где бы она ни существовала .

Даже переменные метода могут находиться в куче, если они захвачены (метод лямбда / anon) или часть (например) блока итератора.




простые меры

Тип значения может быть помечен на STACK, это реализационная деталь, которую он может выделить для некоторой структуры данных футуристистов.

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

Типы ссылок передаются по ссылке (агаи не считают ссылку будет хранить адрес снова в некоторых будущих версиях, он может храниться в некоторых других структурах данных).

поэтому в вашем случае

myInt - это int, который инициализируется в классе, который ссылается на ссылочный тип, поэтому он будет привязан к экземпляру класса, который будет храниться в «HEAP».

я бы предложил, вы можете начать читать блоги, написанные ERIC LIPPERTS.

Блог пользователя Eric




стек

stack представляет собой блок памяти для хранения local variables и parameters . Стек логически растет и сжимается по мере ввода и выхода функции.

Рассмотрим следующий метод:

public static int Factorial (int x)
{
    if (x == 0) 
    {
        return 1;
    }

    return x * Factorial (x - 1);
}

Этот метод является рекурсивным, что означает, что он называет себя. Каждый раз, когда вводится метод, в стеке выделяется новый int , и каждый раз, когда метод завершается, int освобождается .

отвал

  • Куча - это блок памяти, в котором находятся objects (например, reference-type instances ). Всякий раз, когда создается новый объект, он выделяется в куче, и возвращается ссылка на этот объект. Во время выполнения программы куча начинает заполняться по мере создания новых объектов. В среде выполнения есть сборщик мусора, который периодически освобождает объекты из кучи, поэтому ваша программа не запускает Out Of Memory . Объект имеет право на освобождение, как только на него не ссылаются все, что само по себе alive .
  • Куча также сохраняет static fields . В отличие от объектов, выделенных на кучу (которые могут собирать мусор), these live until the application domain is torn down .

Рассмотрим следующий метод:

using System;
using System.Text;

class Test
{
    public static void Main()
    {
        StringBuilder ref1 = new StringBuilder ("object1");
        Console.WriteLine (ref1);
        // The StringBuilder referenced by ref1 is now eligible for GC.

        StringBuilder ref2 = new StringBuilder ("object2");
        StringBuilder ref3 = ref2;
        // The StringBuilder referenced by ref2 is NOT yet eligible for GC.
        Console.WriteLine (ref3); // object2
    }
}    

В приведенном выше примере мы начинаем с создания объекта StringBuilder, на который ссылается переменная ref1, а затем выписываем его содержимое. Этот объект StringBuilder сразу же получает право на сбор мусора, потому что ничто впоследствии не использует его. Затем мы создаем другой StringBuilder, на который ссылается переменная ref2, и копируем эту ссылку на ref3. Несмотря на то, что ref2 не используется после этой точки, ref3 сохраняет один и тот же объект StringBuilder живым, гарантируя, что он не станет пригодным для сбора до тех пор, пока мы не закончим использование ref3.

Вещественные экземпляры (и ссылки на объекты) живут везде, где была объявлена ​​переменная. Если экземпляр был объявлен как поле внутри типа класса или как элемент массива, этот экземпляр живет в куче.




Related

c# .net stack heap