|
|
От: | help-me | |
| Дата: | 05.04.12 09:00 | ||
| Оценка: |
|
||
Получается, любая переменная (или указатель на переменную) кроме адреса должен хранить и тип(размер) переменной, чтобы при создании, удалении или чтении\перезаписи значения этой переменной использовать ровно столько байт, сколько есть в переменной, не больше и не меньше (но тогда на x86 размер указателя или самой переменной должен быть не 4байта(только адрес), а больше?)?Операция разыменования становится возможной исключительно в силу типизации указателей: в типе заложена информация о размере памяти, необходимой для размещения объекта, и о способе интерпретации содержащихся в ней данных, что в совокупности с адресом однозначно идентифицирует объект в памяти.
В первой цитате написано, что не только адрес, но и тип(размер) однозначно идентифицируют, тогда почему во второй цитате говорится только про адрес?Адрес объекта является той характеристикой, которая идентифицирует объект, отличает один объект от всех других объектов в системе.
это только в с++ ? в с# же можно большой объект разместить в стеке (например, создать структуру с множеством полей). получается , в с++ и с# разные стеки?? и почему 1 мбит? в большой программе его может не хватить даже для локальных переменных. и, то есть, стек выделяется для каждого процесса свой личный, а куча для всех процесов общая (куча — вся остальная память, не занятая стеком никакой программы)?Кроме того, размер стека в большинстве случаев ограничен (для программ, разрабатываемых в среде Microsoft Visual Studio, размер стека по умолчанию — 1 Мб), что приводит к невозможности размещения в нём больших объектов, к примеру, тех же массивов.
тот же самый вопрос, если не в куче, а в стеке не хватит памяти (там же только 1 мб), то что?Возникает два вопроса: что подразумевается под термином «выделение памяти» (или «предоставление памяти») и что произойдет, если диспетчер памяти не сможет выделить блок требуемого размера?
когда мы читаем пользовательский ввод, мы же его присваиваем заранее созданному массиву с заданной длиной?Из того, что выделение памяти в стеке возлагается на компилятор, следует, что размер (а значит и тип) размещаемых в стеке объектов должен быть известен на этапе компиляции, что часто бывает невозможно. Простейшая задача обработки массива, размерность и элементы которого вводятся с клавиатуры или из файла, является ярким тому подтверждением.
А почему компилятор автоматически не присваивает ссылке NULL при операции delete?Надо обратить внимание на то, что при удалении адресуемого указателем p1 объекта с самим указателем p1, с его значением ничего не происходит. Оператор delete освобождает память в куче, указатель же p1 располагается в стеке, отведённая под него память будет освобождена только при выходе p1 из области видимости. В ячейках памяти, занимаемых указателем p1 в стеке (см. рис. 17), после выполнения оператора delete будет записана та же информация, что и до вызова этого оператора — число 0xF830 — адрес уже несуществующего объекта.
Таким образом, после выполнения оператора delete мы получаем недействительный указатель (dangling pointer), указатель, который адресует несуществующий объект. Разыменование такого указателя и последующий доступ к объекту в лучшем случае приведёт к немедленному аварийному завершению работы программы, в худшем — к её нестабильному поведению, которое не повторяется от одного запуска программы к другому. На выявление подобных ошибок в реальных программах зачастую уходит много времени и сил. Поэтому в тех случаях, когда планируется дальнейшая работа с указателем на удаляемый объект, имеет смысл сразу после удаления объекта присвоить указателю на него значение NULL, тем самым явно идентифицировав этот указатель как ни на что не указывающий.
будет аварийное завершение, потому что диспетчер памяти посчитает, что мы обращаемся к памяти, которую никто не занимает и не даст прочитать с нее еще не стертые другим процессом данные?Поэкспериментируйте с программой: попробуйте два раза подряд вызвать оператор удаления для одного и того же указателя или разыменовать нулевой указатель, посмотрите на поведение программы в каждом из случаев.