Есть ли указатель на объект декларирующего типа в стеке? - PullRequest
0 голосов
/ 26 февраля 2011

Допустим, у меня есть:

class Animal { }
class Dog : Animal { }

И в основном методе:

Dog dog = new Dog();
Animal animal = dog;

Теперь есть один экземпляр Dog в куче и две переменные встек, с той же ссылкой хранится в них.Следующий шаг -

   //Try to invoke dog.Bark() programatically
   //Try to invoke animal.Bark() programatically

Последний сбой во время выполнения, потому что animal не имеет Bark метода.Таким образом, для двух переменных должно быть что-то другое в стеке.Какая разница, приводящая к ошибке времени выполнения?

Ответы [ 2 ]

5 голосов
/ 26 февраля 2011

Вы правильно выводите ряд деталей реализации.

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

  • неуправляемое хранилище
  • управляемое хранилище
  • временное хранилище

Неуправляемое хранилище выходит за рамки вашего вопроса. Управляемое хранилище - это то, что мы будем называть «кучей». Временное хранилище - это «стек» или регистры, если дрожание умное и регистры доступны, но в качестве упрощающего допущения позволяет игнорировать регистры и просто вызывать пул временного хранилища «стеком».

Существует четыре вида типов:

  • неуправляемые указатели
  • типы значений
  • ссылки, ака, управляемые указатели
  • фактические экземпляры ссылочных типов

Неуправляемые указатели выходят за рамки вашего вопроса. C # позволяет вам манипулировать ссылками («управляемыми указателями») и типами значений напрямую; содержимым экземпляров ссылочного типа манипулируют только через ссылки, и они всегда находятся в куче в реализации CLR. (Ничто не мешает джиттеру создавать экземпляр ссылочного типа в стеке, если у него достаточно смартов, чтобы знать, что объект никогда не нуждается в сборке мусора и не выдерживает метод, но на практике наши дрожания не делают этого, насколько мне известно.)

Другие три вида вещей могут быть в стеке или куче, если необходимо, в зависимости от их времени жизни.

В моем основном методе экземпляр Dog создается и присваивается переменной с именем dog. Я знаю, что происходит в куче, предполагая, что он находится с адреса 0x00FFFF.

Вы предполагаете (правильно), что управляемые ссылки реализованы как адреса в плоском 32-битном адресном пространстве. (На самом деле это не был бы допустимый адрес кучи, но мы позволим ему скользить.) Конечно, реализация CLR не должна использовать необработанные адреса в качестве ссылок. Например, они могут быть непрозрачными ручками в столе, контролируемом ГХ.

В настоящее время я знаю только в стеке, что пространство для собаки имеет значение 0x00FFFFF, но я на 100% уверен, что где-то еще в пространстве для собаки есть свой тип объявления.

Под его "объявленным" типом я думаю, что вы имеете в виду фактический тип времени исполнения экземпляра, Dog. Это сбивающее с толку использование «объявления». Экземпляры не "объявлены"; экземпляры "распределены". Переменные"объявлены", а переменная имеет объявленный тип "Animal".

Да, где-то в фактических данных экземпляра, выделенных для "new Dog ()", есть "токен", который описывает тип времени выполнения объекта. Если вам важны точные сведения о том, как работает токен, задайте другой вопрос.

Я хочу знать подробное объяснение стекового пространства для собаки, в настоящее время я знаю, что там есть ссылочный адрес, что-нибудь еще?

Ваш вопрос неоднозначен, поскольку в стеке есть две переменные, и ни одна из них не названа "собака".

Во время выполнения пространство стека просто содержит управляемую ссылку на пространство кучи, выделенное для экземпляра. Компилятор C # знает, что стековое пространство для dog1 имело тип управляемой ссылки на Animal во время компиляции, а стековое пространство для dog2 имело тип управляемой ссылки на Dog во время компиляции. Поэтому джиттер также знает эту информацию. Джиттер хранит информацию об этом в своих собственных структурах данных; это не загрязняет стек. Джиттер может хранить эту информацию для оптимизации или для целей отладки. Или он может выбросить его, если ему больше не нужна эта информация.

Это опять-таки деталь реализации; джиттер совершенно свободен, чтобы поместить любую дополнительную информацию в стек, который ему нравится.

1 голос
/ 26 февраля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...