Вопрос

Каково расположение памяти в массиве .NET?

Возьмем, к примеру, этот массив:

Int32[] x = new Int32[10];

Я понимаю, что основная часть массива выглядит следующим образом:

0000111122223333444455556666777788889999

Где каждый символ равен одному байту, а цифры соответствуют индексам в массиве.

Кроме того, я знаю, что существует ссылка на тип и syncblock-index для всех объектов, поэтому приведенное выше может быть скорректировано с учетом этого:

ttttssss0000111122223333444455556666777788889999
        ^
        +- object reference points here

Кроме того, необходимо сохранить длину массива, так что, возможно, это более правильно:

ttttssssllll0000111122223333444455556666777788889999
        ^
        +- object reference points here

Является ли это полным?Есть ли еще данные в массиве?

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

Итак, в принципе, для массива, сколько там накладных расходов, это в основном мой вопрос.

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

Это было полезно?

Решение

Отличный вопрос.Я нашел это статья, которая содержит блок-схемы как для типов значений, так и для ссылочных типов.Также смотрите на это Статья в котором Ритчер заявляет:

[snip] каждый массив содержит некоторую дополнительную служебную информацию, связанную с ним.Эта информация содержит ранг массива (количество измерений), нижние границы для каждого измерения массива (почти всегда 0) и длину каждого измерения.Служебные данные также содержат тип каждого элемента в массиве.

Другие советы

Один из способов проверить это - посмотреть на код в WinDbg.Итак, учитывая приведенный ниже код, давайте посмотрим, как это отображается в куче.

var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Первое, что нужно сделать, это найти экземпляр.Поскольку я сделал это локальным в Main(), легко найти адрес экземпляра.

Из адреса мы можем вывести фактический экземпляр, который дает нам:

0:000> !do 0x0141ffc0
Name: System.Int32[]
MethodTable: 01309584
EEClass: 01309510
Size: 52(0x34) bytes
Array: Rank 1, Number of elements 10, Type Int32
Element Type: System.Int32
Fields:
None

Это говорит нам о том, что это наш массив Int32 с 10 элементами и общим размером 52 байта.

Давайте создадим дамп памяти, в которой находится экземпляр.

0:000> d 0x0141ffc0
0141ffc0 [84 95 30 01 0a 00 00 00-00 00 00 00 01 00 00 00  ..0.............
0141ffd0  02 00 00 00 03 00 00 00-04 00 00 00 05 00 00 00  ................
0141ffe0  06 00 00 00 07 00 00 00-08 00 00 00 09 00 00 00  ................
0141fff0  00 00 00 00]a0 20 40 03-00 00 00 00 00 00 00 00  ..... @.........
01420000  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
01420010  10 6d 99 00 00 00 00 00-00 00 01 40 50 f7 3d 03  .m.........@P.=.
01420020  03 00 00 00 08 00 00 00-00 01 00 00 00 00 00 00  ................
01420030  1c 24 40 03 00 00 00 00-00 00 00 00 00 00 00 00  .$@.............

Я вставил скобки для 52 байт.

  • Первые четыре байта являются ссылкой на таблицу методов в 01309584.
  • Затем четыре байта для длины массива.
  • Далее следуют числа от 0 до 9 (каждые четыре байта).
  • Последние четыре байта равны нулю.Я не совсем уверен, но предполагаю, что именно там должна храниться ссылка на массив syncblock, если экземпляр используется для блокировки.

Редактировать:Забыл длину в первом постинге.

Список немного некорректен, потому что, как указывает ромкинс, экземпляр фактически начинается с адреса - 4, а первым полем является Syncblock .

Отличный вопрос!Я хотел увидеть это сам, и это показалось мне хорошей возможностью попробовать CorDbg.exe...

Похоже, что для простых целочисленных массивов формат равен:

ssssllll000011112222....nnnn0000

где s - блок синхронизации, l - длина массива, а затем отдельных элементов.Кажется, что в конце есть, наконец, 0, я не уверен, почему это так.

Для многомерных массивов:

ssssttttl1l1l2l2????????
    000011112222....nnnn000011112222....nnnn....000011112222....nnnn0000

где s - блок синхронизации, t - общее количество элементов, l1 - длина первого измерения, l2 - длина второго измерения, затем два нуля?, за которыми последовательно следуют все элементы и, наконец, снова ноль.

Массивы объектов обрабатываются как целочисленный массив, на этот раз содержимым являются ссылки.Зубчатые массивы - это массивы объектов, ссылки на которые указывают на другие массивы.

Объект array должен был бы хранить, сколько измерений он имеет, и длину каждого измерения.Таким образом, в вашу модель можно добавить по крайней мере еще один элемент данных

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top