Комментарии 26
>> существует 2 вида объектов: value types и reference types,
А вот unsafe pointer — он value-type или reference-type? Он ведь не обычный указатель, по типу того, что используется в Си, так, и не обычная объектная ссылка? Так сколько он байт занимает?
А вот unsafe pointer — он value-type или reference-type? Он ведь не обычный указатель, по типу того, что используется в Си, так, и не обычная объектная ссылка? Так сколько он байт занимает?
0
вообще это уже третий тип в .NET — pointer type. представляет он собой DWORD-адрес на конкретный экземпляр либого value type + bool.
главное предназначение — избежать копирования value type объекта пр присваивании переменной. еще одна роль — вызов нативных функций.
если говорить про DWORD — то 4 байта x86, 8 байт x64.
а уже размеры каждого value type определены в CTS.
главное предназначение — избежать копирования value type объекта пр присваивании переменной. еще одна роль — вызов нативных функций.
если говорить про DWORD — то 4 байта x86, 8 байт x64.
а уже размеры каждого value type определены в CTS.
+2
Если верить Эрику Липперту указатель вполне себе value-type.
0
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Экземпляры объектов ссылочного типа хранятся в управляемой куче всегда; экземпляры объектов типа значений — в стеке управляемого потока среды .NET, за исключением случаев, когда их время жизни должно быть продлено (объект типа значения является полем класса, элементом массива, локальной переменной в блоке итератора или локальной переменной, замкнутой в лямбде/анонимном методе). Интересно что язык C++/CLI позволяет создать массив значений в стеке.
Вывод: автор не так уж и неправ. Reference types хранятся в куче, value types обычно хранятся в стеке. Многие авторы, включая Рихтера, связывают местоположение переменной и её тип таким образом, потому как в большинстве случаев нет необходимости погружаться в низкоуровневые подробности, особенно в подробности реализации компилятора. .NET-программист может ограничится частично верным определением, если только не пишет серьёзно много неуправляемого кода (что, впрочем, и утверждается в рекомендованной статье).
Вывод: автор не так уж и неправ. Reference types хранятся в куче, value types обычно хранятся в стеке. Многие авторы, включая Рихтера, связывают местоположение переменной и её тип таким образом, потому как в большинстве случаев нет необходимости погружаться в низкоуровневые подробности, особенно в подробности реализации компилятора. .NET-программист может ограничится частично верным определением, если только не пишет серьёзно много неуправляемого кода (что, впрочем, и утверждается в рекомендованной статье).
+7
Во-первых, reference создается и живет только в куче, причем не только в GC Heap, но может и в Large Object Heap и т.д.
Во-вторых, время жизни value type определяется declaration scope.
В-третьих, для увеличения продолжительности жизни экземпляра value type, можно и без анонимных методов, и без лямбда-выражений обойтись — использовать boxing (CLR заворачивает значение переменной и помещает в GC Heap).
Возможность нахождения value type объекта в регистре зависит от платформы (так существуют отличия между desktop и server CLR не только в плане сборщика мусора), еще это зависит от самого JIT. Так Windows (и .NET соответственно) запускаются не только на x86, x64, но также еще существует ARM-версия — Windows Embedded. А еще есть .NET MicroFramework с TinyCLR.
Иногда из-за трудности определения возможной жизни объекта, CLR может поместить value type в кучу, для обеспечения максимальной жизни.
И, наконец, это зависит от использование нативного кода.
Как видим, это все детали имплементации конкретной CLR + языковые возможности и требования, например C#
Во-вторых, время жизни value type определяется declaration scope.
В-третьих, для увеличения продолжительности жизни экземпляра value type, можно и без анонимных методов, и без лямбда-выражений обойтись — использовать boxing (CLR заворачивает значение переменной и помещает в GC Heap).
Возможность нахождения value type объекта в регистре зависит от платформы (так существуют отличия между desktop и server CLR не только в плане сборщика мусора), еще это зависит от самого JIT. Так Windows (и .NET соответственно) запускаются не только на x86, x64, но также еще существует ARM-версия — Windows Embedded. А еще есть .NET MicroFramework с TinyCLR.
Иногда из-за трудности определения возможной жизни объекта, CLR может поместить value type в кучу, для обеспечения максимальной жизни.
И, наконец, это зависит от использование нативного кода.
Как видим, это все детали имплементации конкретной CLR + языковые возможности и требования, например C#
+1
Правильно ли я понимаю, что если запросить по адресу размер некоторого класса А, который имеет поля классов В, С..., то SOS вернет суммарный размер класса А, B, C? Или вернет размер класса A + размер ссылок на классы B и С?
0
НЛО прилетело и опубликовало эту надпись здесь
Предположим что он возвращает 1) а не 2). Тогда что должен вернуть sos для класса, который в одном из полей содержит ссылку на самого себя? +inf?
Делаем вывод…
Делаем вывод…
0
SOS вернет суммарный размер класса А, B, C, если использовать !objsize.
Если !do, то без размеров B, C.
Если !do, то без размеров B, C.
0
меня терзают смутные сомнения (с)
размер decimal 16 байт.
размер decimal 16 байт.
0
прежде чем писать, может пробовали хотя бы посмотреть MSDN?
если да, то
1) decimal есть не что иное как 128-битовое число, НО
2) размер колеблется от ±1.0 ✕ 10^28 до ±7.9 ✕ 10^28
3) Содержит 128-битовые (16-байтовые) значения со знаком, представляющие 96-битовые (12-байтовые) целые числа, масштабируемые с переменной степенью 10.
еще можно было просто проверить через !objsize.
и еще посмотреть на расчеты в статье.
и, да, оператор sizeof врет, возвращая размер 16.
если да, то
1) decimal есть не что иное как 128-битовое число, НО
2) размер колеблется от ±1.0 ✕ 10^28 до ±7.9 ✕ 10^28
3) Содержит 128-битовые (16-байтовые) значения со знаком, представляющие 96-битовые (12-байтовые) целые числа, масштабируемые с переменной степенью 10.
еще можно было просто проверить через !objsize.
и еще посмотреть на расчеты в статье.
и, да, оператор sizeof врет, возвращая размер 16.
0
А почему вы не согласны, что decimal занимает 128 бит (16 байт), если он реализован согласно IEEE 754-2008 как decimal128?
Каждый Decimal как видно занимает ровно 0x10 байт.
Посмотрим отдельно на decimal — состоит из 4х int:
Почему врет по вашему sizeof и сколько он должен возвращать?
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct X
{
public decimal f1;
public decimal f2;
public decimal f3;
public decimal f4;
}
!do 02532e2c
Name: Test.Program+X
MethodTable: 002a3094
EEClass: 002a135c
Size: 72(0x48) bytes
(c:\Projects\other\ClassLibrary1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe)
Fields:
MT Field Offset Type VT Attr Value Name
717e7f08 4000001 4 System.Decimal 1 instance 02532e30 f1
717e7f08 4000002 14 System.Decimal 1 instance 02532e40 f2
717e7f08 4000003 24 System.Decimal 1 instance 02532e50 f3
717e7f08 4000004 34 System.Decimal 1 instance 02532e60 f4
Каждый Decimal как видно занимает ровно 0x10 байт.
Посмотрим отдельно на decimal — состоит из 4х int:
Name: System.Decimal
...
Fields:
MT Field Offset Type VT Attr Value Name
71812dbc 400037e 4 System.Int32 1 instance 0 flags
71812dbc 400037f 8 System.Int32 1 instance 0 hi
71812dbc 4000380 c System.Int32 1 instance 0 lo
71812dbc 4000381 10 System.Int32 1 instance 0 mid
...
Почему врет по вашему sizeof и сколько он должен возвращать?
0
Приношу свои извинения. Действительно Decimal составляет 16 байт.
Именно понятие 96-битовых чисел у меня и запечатлелось как норма, что есть неправда.
Именно понятие 96-битовых чисел у меня и запечатлелось как норма, что есть неправда.
0
>Reference type pointer — ссылка на объект, хранящаяся в переменной, размещенной в стеке со смещением 4.
несколько раз перечитал, не понял, что это
и почему его нет в общей сумме?
несколько раз перечитал, не понял, что это
и почему его нет в общей сумме?
0
смотрите, в классе
StringValue представляет собой ссылку размером 4 байта. размер самого экземпляра класса System.String будет равен 26 байт.
привожу цитату из статьи:
class MyExampleClass
{
string StringValue = "String"; // 4 байта
}
StringValue представляет собой ссылку размером 4 байта. размер самого экземпляра класса System.String будет равен 26 байт.
привожу цитату из статьи:
В-третьих, System.String – ссылочный тип, а это значит, что располагается он в GC Heap, и будет состоять из SyncBlock, TypeHandle, Reference point + остальные поля класса. Reference point здесь браться в расчет не будет, т.к. уже посчитан в самом классе MyExampleClass (ссылка 4 байта).
0
а если в моем классе будет 10 строк, то по вашей логике должно быть 10 штук Reference type pointer на схеме?
ссылочные объекты занимают 4 байта (на машине соответствующей разрядности) и вполне попадают в Object fields. незачем пихать в схему лишнюю сущность
тот же Рихтер рисует только Type object ptr и Sync index: www.rvenables.com/linkjackandsufferaccidentaldroptable/clr_via_csharp_f4.9.png
>>Однако в SyncBlock может хранится хеш-код объекта (при вызове метода GetHashCode), или номер записи syncblk
«все смешалось в доме Облонских»
все совсем наоборот. для System.Object в CLR 1-2 в качестве хешкода использовался Sync index (поэтому вызов GetHashCode() на нем приводил к созданию Sync block'a)
подсчет длины строки также выполнен неверно. m_firstChar является первым элементом в последовательности символов, и поэтому присутствует один раз, а вы посчитали его дважды
на ошибку с привязкой value types к стеку вам уже указали
ссылочные объекты занимают 4 байта (на машине соответствующей разрядности) и вполне попадают в Object fields. незачем пихать в схему лишнюю сущность
тот же Рихтер рисует только Type object ptr и Sync index: www.rvenables.com/linkjackandsufferaccidentaldroptable/clr_via_csharp_f4.9.png
>>Однако в SyncBlock может хранится хеш-код объекта (при вызове метода GetHashCode), или номер записи syncblk
«все смешалось в доме Облонских»
все совсем наоборот. для System.Object в CLR 1-2 в качестве хешкода использовался Sync index (поэтому вызов GetHashCode() на нем приводил к созданию Sync block'a)
подсчет длины строки также выполнен неверно. m_firstChar является первым элементом в последовательности символов, и поэтому присутствует один раз, а вы посчитали его дважды
на ошибку с привязкой value types к стеку вам уже указали
0
а если в моем классе будет 10 строк, то по вашей логике должно быть 10 штук Reference type pointer на схеме?
ссылочные объекты занимают 4 байта (на машине соответствующей разрядности) и вполне попадают в Object fields. незачем пихать в схему лишнюю сущность
именно поля класса я имел и ввиду, когда говорил о том, что
Reference point здесь браться в расчет не будет, т.к. уже посчитан в самом классе MyExampleClass (ссылка 4 байта).
если картинка непонятна, то это другое дело.
«все смешалось в доме Облонских»
все совсем наоборот. для System.Object в CLR 1-2 в качестве хешкода использовался Sync index (поэтому вызов GetHashCode() на нем приводил к созданию Sync block'a)
не могу понять что в этих строках непонятного:
Первоначально значение SyncBlock равно нулю. Однако в SyncBlock может хранится хеш-код объекта (при вызове метода GetHashCode), или номер записи syncblk, который помещает в заголовок объекта среда при синхронизации (использование lock, либо напрямую Monitor.Enter).
и, наконец, насчет
подсчет длины строки также выполнен неверно. m_firstChar является первым элементом в последовательности символов, и поэтому присутствует один раз, а вы посчитали его дважды
вообще-то посчитано правильно. m_firstChar является отдельным полем класса + не является shared.
более того, т.к. оно еще и value type, тогда при присваивании ей значения char копируется из массива символов. поправьте меня, если я ошибаюсь.
на ошибку с привязкой value types к стеку вам уже указали
это не является ошибкой. см. мой коммент выше.
0
>если картинка непонятна, то это другое дело.
картинка просто не соотвествует действительности
>Первоначально значение SyncBlock равно нулю. Однако в SyncBlock может хранится хеш-код объекта (при вызове метода GetHashCode), или номер записи syncblk,
вы путаете причину и следствие. не «SyncBlock может хранить хеш-код», а «Sync Index может использоваться в качестве хеш-кода»
>это не является ошибкой. см. мой коммент выше.
в той формулировке, как это сделано в статье, именно что ошибка. а вашим комментариям, к сожалению, доверять нельзя
почиайте Липперта что ли:
blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx
>вообще-то посчитано правильно. m_firstChar является отдельным полем класса
>тогда при присваивании ей значения char копируется из массива символов.
возьмите отладчик и посмотрите побайтно, что в строке есть и чего там нет
картинка просто не соотвествует действительности
>Первоначально значение SyncBlock равно нулю. Однако в SyncBlock может хранится хеш-код объекта (при вызове метода GetHashCode), или номер записи syncblk,
вы путаете причину и следствие. не «SyncBlock может хранить хеш-код», а «Sync Index может использоваться в качестве хеш-кода»
>это не является ошибкой. см. мой коммент выше.
в той формулировке, как это сделано в статье, именно что ошибка. а вашим комментариям, к сожалению, доверять нельзя
почиайте Липперта что ли:
blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx
>вообще-то посчитано правильно. m_firstChar является отдельным полем класса
>тогда при присваивании ей значения char копируется из массива символов.
возьмите отладчик и посмотрите побайтно, что в строке есть и чего там нет
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Размеры CLR-объектов. Точное определение