пролистал Рихтера (CLS via C#). он прямым текстом пишет «в управляемой куче последовательно созданные объекты гарантированно будут расположены друг за другом»
конечно, ремарки насчет выравнивания, поколений и больших объектов остаются в силе
похоже, Вы правы, а я ошибся
действительно, ptr[-1] и ptr[-2] будут искомыми полями
я опирался не на адрес поля &obj.Val, а на значение, содержаееся непосредственно в ссылке obj. но похоже, она указывает в «середину» объекта, а именно — в ptr[-1] в Вашей нотации
размер реальной памяти Вы не сосчитали, но это уже сделано в комментариях ниже.
но Вы оба опирались на адрес переменной Val. если бы переменная была приватной и имела геттер/сеттер, или если бы даже ее вообще не было, Вы бы смогли тогда достучаться до этих полей?
вопрос динамического выделения памяти — отдельная большая тема, в двух словах ее никак не опишешь
если вкратце, основная проблема — утилизация уже освобожденной памяти (т.е. повторное использование участков, которые были ранее выделены и потом освободились), поэтому объекты желательно держать как можно плотнее. в неуправляемых языках, типа с или с++ (ну также и собственно на уровне ос происходит, хотя с++ дублирует этот механизм) выделяемая память имеет указатель размера, занимаемого объектом. при освобождении указатель вместе с размером добавляется в т.н. список свободных областей. есть хорошая статья джоэля, затрагивающая эту тему: russian.joelonsoftware.com/Articles/BacktoBasics.html. она будет полезна любому, на мой взгляд
в управляемой среде .NET ситуация принципиально другая. поскольку инфраструктура .NET контролирует каждую ссылку на любой объект, имеется возможность перемещать объекты из одной области памяти в другую прозрачно для пользователя, обновляя при этом все ссылки. сборщик мусора действует именно так, уплотняя объекты как можно сильнее — чтобы свободная память была участком максимального размера.
кроме того, следует упомянуть о поколениях сборщика мусора (объекты в пределах поколения «группируются»), о выравнивании памяти (для эффективности границы объектов должны быть выровнены по некоторому размеру, обычно размеру указателя), о больших объектах (в .NET большие объекты не переносятся с места на место, ибо это накладно, а располагаются в отдельной области управляемой кучи).
все это очень большая тема )
очень хорошая попытка, но к сожалению, не засчитывается
размер Вы посчитали верно (т.е. такой способ тоже годится — допущение, что два объекта одного типа имеют одинаковую внутреннюю структуру — достаточно логичное)
необходимое условие — запускать код в отдельной программе, не создавая других объектов — тоже верно
а давайте подумаем, откуда могут появится дырки между объектами? только от удаленных объектов, не так ли?
кроме того, разве сборщик мусора не перемещает объекты в начало кучи?
нет, по нескольким причинам
во-1, Вы полагаете, что объект внутри содержит три 32битных поля, а это еще надо доказать
во-2, Вы почему-то решили, что дополнительные поля находятся перед «явным» полем, а это весьма сомнительное утверждение
но направление выбрано правильное, продолжайте думать )
и да и нет
да — потому что Вы первый догадались применить ансейф код, и Ваш метод даже дает правильные резулататы
нет — потому что Вы используете то, что истинный размер указан где-то в типе. это специфическая деталь реализации, и она может менятся, а может и вообще врать.
ну и вдобавок требуется указать содержимое полей
мне как раз и не нужно, чтоб он выходил на главную страницу, потому что тогда меня минусуют те, кому дотнет по барабану — похоже, я зачастил своими этюдами )
а делать закрытым тоже не хочу, так как он скорее предназначен для тех, у кого нет инвайта на хабр, нежели для тех, у кого есть
нет, поскольку GetTotalMemory дает лишь приблизительную оценку, а с большим количеством объектов ответы будут еще сильнее отличаться
собственно, правильный ответ в комментариях уже есть, но нет доказательства
тоже нет, при передаче в неуправляемый код никакие внутренние структуры дотнета просто так не передаются, нет в этом смысла
да и это нарушает ограничение этого этюда, ведь на шарпе неуправляемы код не напишешь (насколько я помню ))
да, правильный ответ 12, и тему я взял именно у Рихтера )
но теория теорией, а практическое подтверждение тоже требуется
для Вас еще последующие части будут )
Marshal.SizeOf вернет в данном случае объем, занимаемый полями, т.е. 4 байта
профайлер я пытался вчера дернуть из шарпа, но не очень получилось, да и неточные он данные дает
конечно, ремарки насчет выравнивания, поколений и больших объектов остаются в силе
похоже, Вы тоже выведите искомые поля объекта x2
действительно, ptr[-1] и ptr[-2] будут искомыми полями
я опирался не на адрес поля &obj.Val, а на значение, содержаееся непосредственно в ссылке obj. но похоже, она указывает в «середину» объекта, а именно — в ptr[-1] в Вашей нотации
размер реальной памяти Вы не сосчитали, но это уже сделано в комментариях ниже.
но Вы оба опирались на адрес переменной Val. если бы переменная была приватной и имела геттер/сеттер, или если бы даже ее вообще не было, Вы бы смогли тогда достучаться до этих полей?
если вкратце, основная проблема — утилизация уже освобожденной памяти (т.е. повторное использование участков, которые были ранее выделены и потом освободились), поэтому объекты желательно держать как можно плотнее. в неуправляемых языках, типа с или с++ (ну также и собственно на уровне ос происходит, хотя с++ дублирует этот механизм) выделяемая память имеет указатель размера, занимаемого объектом. при освобождении указатель вместе с размером добавляется в т.н. список свободных областей. есть хорошая статья джоэля, затрагивающая эту тему: russian.joelonsoftware.com/Articles/BacktoBasics.html. она будет полезна любому, на мой взгляд
в управляемой среде .NET ситуация принципиально другая. поскольку инфраструктура .NET контролирует каждую ссылку на любой объект, имеется возможность перемещать объекты из одной области памяти в другую прозрачно для пользователя, обновляя при этом все ссылки. сборщик мусора действует именно так, уплотняя объекты как можно сильнее — чтобы свободная память была участком максимального размера.
кроме того, следует упомянуть о поколениях сборщика мусора (объекты в пределах поколения «группируются»), о выравнивании памяти (для эффективности границы объектов должны быть выровнены по некоторому размеру, обычно размеру указателя), о больших объектах (в .NET большие объекты не переносятся с места на место, ибо это накладно, а располагаются в отдельной области управляемой кучи).
все это очень большая тема )
размер Вы посчитали верно (т.е. такой способ тоже годится — допущение, что два объекта одного типа имеют одинаковую внутреннюю структуру — достаточно логичное)
необходимое условие — запускать код в отдельной программе, не создавая других объектов — тоже верно
а вот содержимое выведено неправильно
см. iaroshenko.habrahabr.ru/blog/77275/#comment_2250134
кроме того, разве сборщик мусора не перемещает объекты в начало кучи?
ну и вывести их значение
их смысл будет проверятся в следующем этюде
во-1, Вы полагаете, что объект внутри содержит три 32битных поля, а это еще надо доказать
во-2, Вы почему-то решили, что дополнительные поля находятся перед «явным» полем, а это весьма сомнительное утверждение
но направление выбрано правильное, продолжайте думать )
но если там такие монстры, как на rsdn.ru, то я пока воздержусь
там у них такие этюды, которые с решением не сразу-то поймешь
да — потому что Вы первый догадались применить ансейф код, и Ваш метод даже дает правильные резулататы
нет — потому что Вы используете то, что истинный размер указан где-то в типе. это специфическая деталь реализации, и она может менятся, а может и вообще врать.
ну и вдобавок требуется указать содержимое полей
а делать закрытым тоже не хочу, так как он скорее предназначен для тех, у кого нет инвайта на хабр, нежели для тех, у кого есть
собственно, правильный ответ в комментариях уже есть, но нет доказательства
да и это нарушает ограничение этого этюда, ведь на шарпе неуправляемы код не напишешь (насколько я помню ))
но теория теорией, а практическое подтверждение тоже требуется
для Вас еще последующие части будут )
профайлер я пытался вчера дернуть из шарпа, но не очень получилось, да и неточные он данные дает