C#: Используя типы указателей как поля?

Лучший тест должен был бы следить за Вашим использованием памяти Perfmon и счетчики памяти CLR. Мое понимание - то, что целая причина Вы хотите использовать Строку. Формат вместо того, чтобы просто связать строки, так как строки неизменны, Вы излишне обременяете сборщик "мусора" временными строками, которые должны быть исправлены в следующей передаче.

StringBuilder и Строка. Формат, хотя потенциально медленнее, является большей эффективной памятью.

, Что так плохо о конкатенации строк?

12
задан JulianR 9 November 2009 в 21:52
поделиться

5 ответов

Безопасно ли когда-нибудь использовать эту конструкцию? Имею ввиду для длительного хранения в куче.

Да. Обычно это глупо, болезненно и ненужно, но это возможно.

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

Нет. Вот почему мы заставляем вас пометить его как небезопасный.

Полагаю, что нет, это сделало бы эту конструкцию очень небезопасной, верно?

Верно.

Я уверен, что есть намного лучшие альтернативы этому, но назовите это болезненным любопытством.

Конечно, есть.

гарантированно ли указатель будет продолжать указывать на то, на что вы его изначально указали?

Нет, если вы не убедитесь, что это произойдет. Это можно сделать двумя способами.

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

  • Исправить переменную на месте с помощью оператора fixed.

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

Выполнение любого из этих действий с высокой вероятностью снизит производительность сборщика мусора.

Способ второй: не использовать ссылки на память, которые сборщик мусора может переместить. Это можно сделать двумя способами:

  • Принимать только адреса локальных переменных, параметров значений или блоков, выделенных стеком. Конечно, при этом вы должны убедиться, что указатели не сохранятся дольше, чем соответствующий кадр стека, в противном случае вы ссылаетесь на мусор.

  • Выделите блок из неуправляемой кучи, а затем используйте указатели внутри этого блок. По сути, реализовать свой собственный менеджер памяти. От вас требуется правильно реализовать ваш новый пользовательский менеджер памяти. Будьте осторожны.

12
ответ дан 2 December 2019 в 07:21
поделиться

Почему бы и нет:

struct Node
{
    public Node NextNode;
}

или хотя бы:

struct Node
{
    public IntPtr NextNode;
}

Вы можете использовать оператор fixed , чтобы предотвратить перемещение указателей в GC.

2
ответ дан 2 December 2019 в 07:21
поделиться

Опасная идея, но она может работать:

Когда ваш массив структур превышает определенный размер (85000 байт), он будет размещен в куче больших объектов где блоки сканируются и собираются, но не перемещаются ...

В связанной статье указывается на опасность того, что новая версия CLR может перемещать данные на LOH ...

2
ответ дан 2 December 2019 в 07:21
поделиться

Некоторые очевидные проверки целостности исключены. Очевидная проблема заключается в том, что вам нужно выделить больше, чем вам нужно, потому что вы не можете перераспределить буфер, как предполагает ключевое слово fixed .

public unsafe class NodeList
{
    fixed Node _Nodes[1024];
    Node* _Current;

    public NodeList(params String[] data)
    {
        for (int i = 0; i < data.Length; i++)
        {
            _Nodes[i].Data = data[i];
            _Nodes[i].Next = (i < data.Length ? &_Nodes[i + 1] : null);     
        }

        _Current = &_Nodes[0];
    }

    public Node* Current()
    {
        return _Current++;  
    }
}

public unsafe struct Node
{
    public String Data;
    public Node* Next;
}
3
ответ дан 2 December 2019 в 07:21
поделиться

Да, сборщик мусора может перемещать объекты и, нет, он не будет обновлять ваши указатели. Вам нужно исправить объекты, на которые вы указываете. Дополнительную информацию можно найти в этом объяснении управления памятью .

Вы можете исправить такие объекты, как этот:

  unsafe {
     fixed (byte* pPtr = object) {
         // This will fix object in the memory
        }
     }
  }

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

2
ответ дан 2 December 2019 в 07:21
поделиться
Другие вопросы по тегам:

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