#cpp #память
У меня есть некоторые трудности в понимании работы C++ с памятью. Надеюсь их разрешить. Представим, существует некоторая программа, написанная на языке C++, и ее только запустили на компьютере (x86_64). Насколько мне известно, при запуске программе выделяются две структуры памяти - стек и куча. В стеке хранится информация о передаваемых значениях функций, адреса и, может, еще чего. В куче же некоторые ресурсы программы и другие данные: пользовательские строки, переменные - в общем, данные, появившиеся во время работы программы. Термин "пул" - что он означает? Он как-то связан с кучей? Если да, то как? Когда ОС передает кучу программе - она заполнена нулями? Если так - почему при выводе строки, не имеющей \0, могут появляться лишние символы? Здесь об этом более подробно И почему в таком случае переменная, при ее создании, содержит произвольные данные из памяти? Оператор new может запрашивать дополнительную память у ОС даже том случае, если куча имеет свободное пространство? Возможно ли при такой операции array = new char[7]; выделение более семи байт? Округление для выравнивания? Аллокатор - механизм для выделения памяти в куче?
Ответы
Ответ 1
Насколько мне известно, при запуске программе выделяются две структуры памяти - стек и куча. Ну, вообще-то при запуске программы выделяются три структуры памяти: куча, стек и статические данные. Но это уже вопрос выбранного уровня абстракции. На уровне языка С++, например, не констатируется существования никакого "стека". Также, с точки зрения языка, не оговаривается в какой памяти живут временные объекты. Формально это может быть четвертым типом памяти. На уровне аппаратуры регистры процессора являются отдельным типом памяти. В куче же некоторые ресурсы программы и другие данные: пользовательские строки, переменные - в общем, данные, появившиеся во время работы программы. В куче традиционно находятся только безымянные объекты, созданные через средства распределения динамической памяти. Термин "пул" - что он означает? Он как-то связан с кучей? Если да, то как? "Пул" - слишком расплывчатый термин. Да, обычно это отдельное хранилище, ответственное за динамическое распределение ресурсов, каким-то образом связанных между собой. Характер этой связи может быть любым. Это могут быть тесно связанные объекты одного типа, объекты одного размера и т.п. А могут быть совершенно никак внешне не похожие друг на друга ресурсы, но распределяемые одним потоком выполнения. Иногда пул организовывают лишь потому, что всю выделенную в нем память можно потом легко освободить "одним махом" вместе с самим пулом, вместо того, чтобы скурпулезно освобождать маленькие блоки по одному. В общем, если у вас есть такая-то причина распределять память для какого-то набора объектов в некотором отдельном условно-обособленном хранилище - то вы организовываете для них пул. Когда ОС передает кучу программе - она заполнена нулями? Никто не знает, когда и как ОС передает кучу программе. Это определяется реализацией. Современные ОС строятся на механизме виртуальной памяти. Там ничего ничем не заполнено, потому что заполнять заранее просто нечего - физически памяти изначально не существует, она "материализуется на лету" по мере обращения программы к ней. А уж чем она при этом будет заполняться - это уж как попросите. Если так - почему при выводе строки, не имеющей \0 могут появляться лишние символы? Потому что, во-первых, даже память полученная от ОС не обязательно "материализуется" в заполненном нулями состоянии. Во-вторых, с чего вы вообще взяли, что эта память только что получена "от ОС"? Эта память могла уже давно находиться в распоряжении вашей программы, быть использована для тысяч разных применений и хранить оставшийся в ней мусор. ОС тут вообще ни при чем. Оператор new может запрашивать дополнительную память у ОС даже том случае, если куча имеет свободное пространство? Во-первых, может. Например, если вы через new запросили "большой" блок памяти. Во-вторых, почему вы вообще отделяете "кучу" от "ОС"? На некоторых платформах поддержка языковой "кучи" уже давно перекочевала из библиотеки времени выполнения в API операционной системы. Возможно ли при такой операции array = new char[7]; выделение более семи байт? Округление для выравнивания? Какой именно размер имеется в виду? Тот, который доступен пользователю, или тот, который запрашивается в куче? Каждый выделенный блок памяти обычно содержит в себе еще и служебную информацию, поэтому практически гарантированно, что будет выделено больше 7 байт. Даже вне соображений выравнивания. Аллокатор - механизм для выделения памяти в куче? Что имеется в виду под словом "аллокатор"??? Английское слово? std::allocator? Аллокатор мелких блоков от Васи из третьего подъезда? Что-то еще?Ответ 2
Вы путаете распределение памяти в C/C++ программе и соглашение по выделению памяти операционной системой при запуске программы. При запуске программе, каким-то образом выделяется память, возможно, что это будет просто кусок памяти который необходимо распределить и под кучу и под стек и под статические данные. Прослойкой между ОС и программой на конкретном языке является стартовый код, зачастую написанный на ассемблере, он то как раз запускает функцию main() в C.
Комментариев нет:
Отправить комментарий