Re: То, что не описано в статье, но всех интересует
От: DarkTranquillity  
Дата: 05.04.12 10:34
Оценка: 4 (1)
Здравствуйте, help-me, Вы писали:

HM>

HM>Операция разыменования становится возможной исключительно в силу типизации указателей: в типе заложена информация о размере памяти, необходимой для размещения объекта, и о способе интерпретации содержащихся в ней данных, что в совокупности с адресом однозначно идентифицирует объект в памяти.

HM>Получается, любая переменная (или указатель на переменную) кроме адреса должен хранить и тип(размер) переменной, чтобы при создании, удалении или чтении\перезаписи значения этой переменной использовать ровно столько байт, сколько есть в переменной, не больше и не меньше (но тогда на x86 размер указателя или самой переменной должен быть не 4байта(только адрес), а больше?)?

Нет, размер объекта и смещения его полей известны на этапе компиляции, поэтому для доступа к объекту достаточно знать адрес его "начала" — остальное компилятор посчитает сам.

HM>

HM>Адрес объекта является той характеристикой, которая идентифицирует объект, отличает один объект от всех других объектов в системе.

HM>В первой цитате написано, что не только адрес, но и тип(размер) однозначно идентифицируют, тогда почему во второй цитате говорится только про адрес?

Не докапывайтесь к ерунде.

HM>

HM>Кроме того, размер стека в большинстве случаев ограничен (для программ, разрабатываемых в среде Microsoft Visual Studio, размер стека по умолчанию — 1 Мб), что приводит к невозможности размещения в нём больших объектов, к примеру, тех же массивов.

HM>это только в с++ ? в с# же можно большой объект разместить в стеке (например, создать структуру с множеством полей). получается , в с++ и с# разные стеки?? и почему 1 мбит? в большой программе его может не хватить даже для локальных переменных. и, то есть, стек выделяется для каждого процесса свой личный, а куча для всех процесов общая (куча — вся остальная память, не занятая стеком никакой программы)?

Для компьютеров на платформе x86 и x64 по умолчанию выделяется стек объемом 1 МБ. Для компьютеров на платформе Itanium по умолчанию выделяется стек объемом 4 МБ.

— МСДН
Нет, С++ тут не причем. Вообще, информация о размере стека хранится в заголовке exe-файла, то есть заполняет это линкер, настраивается в опциях проекта. (компилятор вообще не при делах). Но, судя по описанию CreateThread, именно такой размер стека по умолчанию зашит в системе.
Ахринеть, это что за "большая" такая программа?
Стек выделяется свой для каждого потока, а куча — одна глобальная на процесс, плюс можно создавать свои кучи.

HM>

HM>Возникает два вопроса: что подразумевается под термином «выделение памяти» (или «предоставление памяти») и что произойдет, если диспетчер памяти не сможет выделить блок требуемого размера?

HM>тот же самый вопрос, если не в куче, а в стеке не хватит памяти (там же только 1 мб), то что?

То ОС бросит исключение SEH stack overflow.

HM>

HM>Из того, что выделение памяти в стеке возлагается на компилятор, следует, что размер (а значит и тип) размещаемых в стеке объектов должен быть известен на этапе компиляции, что часто бывает невозможно. Простейшая задача обработки массива, размерность и элементы которого вводятся с клавиатуры или из файла, является ярким тому подтверждением.

HM>когда мы читаем пользовательский ввод, мы же его присваиваем заранее созданному массиву с заданной длиной?

Вот потому и используются указатели. То, чему Вы присваиваете пользовательский ввод — Ваше дело. В современных ОС и языках есть функции, позволяющие задавать максимальное количество символов, дабы не получить переполнение буфера со всеми вытекающими.


HM>

HM>Надо обратить внимание на то, что при удалении адресуемого указателем p1 объекта с самим указателем p1, с его значением ничего не происходит. Оператор delete освобождает память в куче, указатель же p1 располагается в стеке, отведённая под него память будет освобождена только при выходе p1 из области видимости. В ячейках памяти, занимаемых указателем p1 в стеке (см. рис. 17), после выполнения оператора delete будет записана та же информация, что и до вызова этого оператора — число 0xF830 — адрес уже несуществующего объекта.
HM>Таким образом, после выполнения оператора delete мы получаем недействительный указатель (dangling pointer), указатель, который адресует несуществующий объект. Разыменование такого указателя и последующий доступ к объекту в лучшем случае приведёт к немедленному аварийному завершению работы программы, в худшем — к её нестабильному поведению, которое не повторяется от одного запуска программы к другому. На выявление подобных ошибок в реальных программах зачастую уходит много времени и сил. Поэтому в тех случаях, когда планируется дальнейшая работа с указателем на удаляемый объект, имеет смысл сразу после удаления объекта присвоить указателю на него значение NULL, тем самым явно идентифицировав этот указатель как ни на что не указывающий.

HM>А почему компилятор автоматически не присваивает ссылке NULL при операции delete?

HM>

HM>Поэкспериментируйте с программой: попробуйте два раза подряд вызвать оператор удаления для одного и того же указателя или разыменовать нулевой указатель, посмотрите на поведение программы в каждом из случаев.

HM>будет аварийное завершение, потому что диспетчер памяти посчитает, что мы обращаемся к памяти, которую никто не занимает и не даст прочитать с нее еще не стертые другим процессом данные?

Наконец-то! Вы почти угадали! Только не даст он прочитать по нулевому указателю, а другие процессы вообще не причем, потому что адресные пространства процессов никак не зависят друг от друга — виртуальный режим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.