воскресенье, 16 октября 2011 г.

Немного о malloc и выделение памяти

malloc в glibc-е давно-давно выделяет память через mmap, и соответственно - если не инициализировать эту память, она так-же, будет нерезидентна и вообще, не будет заниматься. malloc(1024*1024*1024*2) отрабатывает мигом, и никак не сказывается на том, сколько в системе свободно памяти, а вот после memset-а по этому региону - память реально выделяется.




читаем в частности malloc(3):
When using malloc() be careful to avoid the following idiom:
           if ((p = malloc(num * size)) == NULL)
                   err(1, "malloc");
     The multiplication may lead to an integer overflow.  To avoid this,
     calloc() is recommended. 
Про выделение памяти:

Стек — это более быстрая память, но у неё есть недостаток, он работает по принципу FILO (первый пришёл — последний ушёл), то есть данные, которые попали в него позже, освободятся раньше. Для кучи вы можете в любой момент попросить любое количество свободной памяти (оператор new) и когда она вам будет не больше нужна, вы её вернёте системе (оператор delete). Для стека это невозможно. Размещение в нём данных происходит автоматически. Например, при вызове функции, все её аргументы помещаются в стек и локальные переменные тоже. Когда функция отработала, это всё из стека удаляется.

Кстати, помимо стека и кучи есть ещё сегмент, в котором живут статические переменные.



Чуть подробнее:


Стек, это структура данных по принципу "последний вошел - первый вышел". Используется в процессорах в первую очередь для организации вызовов функций, которые как правило вложены друг в друга. Обычно это происходит так: при входе в функцию, в стек помещаются параметры и адрес возврата - адрес следующей за вызовом команды. Сама функция внутри себя еще расширяет стек под локальные переменные. При выходе из функции стек восстанавливается к виду, какой он был до входа в функцию. Именно поэтому локальные переменные и параметры функций нельзя использовать за пределами функции - их уже нет в стеке. Когда мы вышли из функции, из стека также извлекается адрес возврата, ранее туда помещенный, и выполнение продолжается с него, т.е. со следующей за вызовом функции команды. И теперь нам снова доступны параметры и переменные из этой внешней вызывающей функции. И так будет независимо от того, насколько глубоко в вызовы функций мы зашли. Если функция 1 вызвала функцию 2, которая в свою очередь вызвала функцию 3, то у нас внизу стека будут параметры и переменные ф-ции 1, чуть выше - ф-ции 2, а еще выше - ф-ции 3. Доступны на данном этапе нам только параметры ф-ции 3, но стоит из нее выйти, и у нас снова переменные и параметры ф-ции 2. В общем, у объектов на стеке время жизни ограничено временем существования данного фрагмента стека, а область видимости ограничена тем, является ли данная область стека сейчас самой "верхней".
А куча - это динамическая память. Ты выделяешь из нее фрагмент нужного размера, и можешь обращаться к ней из любой части программы, имея валидный указатель. Время жизни объектов на куче такое, какое потребуется, они не "умирают" при выходе за область видимости. В большинстве языков ты сам должен очистить выделенную под объект память, в других же это сделает уборщик мусора.

Цитата (rockbear @ 31.08.09, 17:37)
значит чтобы получить ее значение нужно извлечь еще те переменные, которые находятся перед ней?


Нет :D Указатель на вершину стека храниться в специальном регистре, а когда тебе нужно извлечь переменную не из вершины, то берется значение из регистра плюс нужное смещение. Но учти, что функция ничего не знает о состоянии стека глубже своих переменных и параметров, и соответственно, не может обращаться к параметрам и переменным функции, ее вызвавшей



И плюс разный срок хранения данных: в стеке пока выполняется данная процедура, а в куче пока выполняется данный процесс 

Комментариев нет:

Отправить комментарий