Как стать автором
Обновить
37
0

Пользователь

Отправить сообщение
using System;
using System.Runtime.InteropServices;

public static class ObjectExtensions
{
  [StructLayout(LayoutKind.Explicit)]
  internal struct MyStruct
  {
    [FieldOffset(0)]
    public Int32 Value1;

    [FieldOffset(4)]
    public object Value2;
  }

  public static unsafe int GetAddr(this object o)
  {
    MyStruct ms = new MyStruct();
    ms.Value2 = o;
    int* ptr = &ms.Value1;
    return ptr[1];
  }

  public static unsafe void PrintObject(this int ptr, int offset, int count, string descr)
  {
    Console.WriteLine("Printing {0} object at addr : {1}", descr, ptr);
    int* ptr2 = (int*)ptr;
    for (int i = 0; i < count; ++i)
    {
      Console.WriteLine("-- {0}", ptr2[offset + i]);
    }
  }
}

class X
{
  public int Val {get; set; }
}

class App
{
  static unsafe void Main()
  {
    const int INT_BYTES = 4;
    object x = new X() { Val = 101 };
    {
      object y = new X() { Val = 257 };
      int size = y.GetAddr() - x.GetAddr();
      Console.WriteLine("Size is {0} bytes", size);
      x.GetAddr().PrintObject(-1, size/INT_BYTES, "x");
      y.GetAddr().PrintObject(-1, size/INT_BYTES, "y");
    }
  }
}

* This source code was highlighted with Source Code Highlighter.
пролистал Рихтера (CLS via C#). он прямым текстом пишет «в управляемой куче последовательно созданные объекты гарантированно будут расположены друг за другом»
конечно, ремарки насчет выравнивания, поколений и больших объектов остаются в силе
да, смотрите мое дополнение: iaroshenko.habrahabr.ru/blog/77275/#comment_2253737
похоже, Вы тоже выведите искомые поля объекта 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, то я пока воздержусь
там у них такие этюды, которые с решением не сразу-то поймешь
и то и другое
и да и нет
да — потому что Вы первый догадались применить ансейф код, и Ваш метод даже дает правильные резулататы
нет — потому что Вы используете то, что истинный размер указан где-то в типе. это специфическая деталь реализации, и она может менятся, а может и вообще врать.
ну и вдобавок требуется указать содержимое полей
мне как раз и не нужно, чтоб он выходил на главную страницу, потому что тогда меня минусуют те, кому дотнет по барабану — похоже, я зачастил своими этюдами )
а делать закрытым тоже не хочу, так как он скорее предназначен для тех, у кого нет инвайта на хабр, нежели для тех, у кого есть
нет, поскольку GetTotalMemory дает лишь приблизительную оценку, а с большим количеством объектов ответы будут еще сильнее отличаться
собственно, правильный ответ в комментариях уже есть, но нет доказательства
правильнее сказать: знаете почти всю теорию, сорри )
правильно, и Вы даже почти знаете всю теорию для следующего этюда, но код все равно нужен )
тоже нет, при передаче в неуправляемый код никакие внутренние структуры дотнета просто так не передаются, нет в этом смысла
да и это нарушает ограничение этого этюда, ведь на шарпе неуправляемы код не напишешь (насколько я помню ))
да, правильный ответ 12, и тему я взял именно у Рихтера )
но теория теорией, а практическое подтверждение тоже требуется
для Вас еще последующие части будут )
Marshal.SizeOf вернет в данном случае объем, занимаемый полями, т.е. 4 байта
профайлер я пытался вчера дернуть из шарпа, но не очень получилось, да и неточные он данные дает

Информация

В рейтинге
Не участвует
Откуда
Киев, Киевская обл., Украина
Зарегистрирован
Активность