Malloc free() в функцие.

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Во-первых ты упомянул о возврате указателя на локальный объект. Это как раз тот случай, когда слышал звон, да не знаю где он. Для того, чтобы подогнать наш случай под упомянутую проблему, следует изменить функцию copy_string следующим образом:

Код: Выделить всё

char* copy_string(const char* sz)
{
  char ret[1024];
  strcpy(ret, sz);
  return ret;
}
Почему её следуют изменить именно так, читай ниже.

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

Давайте начнём с простого. Сколько типов памяти у нас есть в С++? Правильный ответ "3". Это статическая, автоматическая и динамическая память. Автоматическую память иногда ещё называют стековой.

1. Статическая память выделяется под объекты еще до начала работы программы во время стартовой инициализации. Во время работы программы эту память не нужно ни захватывать, ни освобождать следовательно, все переменные расположенные в этой памяти (а это глобальные и статические переменные) имеют время жизни равное времени жизни самой программы.

2. Автоматическая память, это память, выделяемая на стеке. В неё попадают все локальные переменные, объявленные без спецификатора static.

3. Динамическая память. Её ещё называют кучей (англ. heap). Это специальная область памяти, которая не побита на кусочки с самого начала и не закреплена за определёнными переменными, подобно статической памяти. Это в полном понимании этого слова является живой "куча" от которой программа во время выполнения откусывает кусочки, использует эти их, а затем освобождает, чтобы, вполне возможно, вскоре снова захватить тот же самый кусок памяти, но использовать его под совсем другие нужды. В динамической памяти располагаются динамически создаваемые программные объекты, то есть те, для которых мы делаем new или malloc. Ещё с динамической памятью неразрывно связана такая сущность, как менеджер памяти. Это подпрограмма (фактически точкой входа в неё является системная функция malloc), которая занимается поиском и выделением указанного размера памяти в куче. По-хорошему, по менеджеру памяти следует написать отдельную статью, потому далее в эту область углубляться не будем.

Далее рассмотрим некоторые параметры переменных, расположенный в этих трёх типах памяти.

Время жизни:

1. Переменная статической памяти - время жизни программы. Здесь следует сделать заметку о локально определённых статических переменных. У них время жизни такое же, как время жизни глобальных переменных, однако у них отложена инициализация (об инициализации, кстати, я с месяц назад писал отдельную статью)

2. Переменная автоматической памяти - внутри текущего блока кода, ограниченного {}.

3. Переменная динамической памяти - от new (malloc) до delete (free).

Скорость выделения памяти:

1. Переменная статической памяти - время выделения = 0 (до входа в main она уже выделена).

2. Переменная автоматической памяти - крайне быстрое выделение (вычитание из ESP необходимого числа байт для того, чтобы разместить переменную в стеке)

3. Переменная динамической памяти - самое медленное выделение, так как идёт обращение к менеджеру памяти. Следует пробежать по куче, отыскать среди фрагментировано занятых кусков памяти диапазон байт, в которые поместится указанная переменная, затем пометить эту память, как занятую и вернуть её - это всё время.

Далее немного остановимся на плюсах и минусах.

Статическая память: казалось здесь одни плюсы. Время выделения нулевое, время жизни - пока работает программа. Однако если мы разместим все наши переменные в глобальной видимости данных или сделаем их статическими, то мы очень быстро исчерпаем всю память. Вполне возможно, что некоторые переменные, нам нужны только во время выполнения некой функции, другие на дольшее время, но всё равно содержать их на протяжении работа всей программы нецелесообразно, так как они могут быть очень-очень большими, посему освобождать их следует так быстро, как это возможно.

Автоматическая память. Из плюсов: время выделения крайне быстрое, текущий скоп можно настроить так, что как только переменная будет не нужна, она умрёт. Из минусов: то, что переменная живёт только внутри текущего блока {} это ещё и её минус. Как только нам нужно добиться того, что переменная жило за пределами текущей функции, на приходиться размещать её в в другой памяти.

Динамическая память. Из плюсов: самая гибкая память, выделить можно столько, сколько решили во время работы программы, жить объект будет вне зависимости от того в каких скобках он родился, очистить можно насильно до завершения программы. Из минусов: очень медленно выделение. Если злоупотреблять new/delete то это может стать настоящим ударом по производительности программы.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

&quot писал(а): статическая, автоматическая и динамическая
Согласен. А перемнные? Ведь никто не отменял понятие области видимости. Насколько я знаю, все переменные, которые c++ размещает в автоматической памяти в других языках называются локальными. Те, что в статической, за исключением случаев примения спецификатора static для переменных функции, сохраняющих своё значение от вызова к вызову - глобальными, а в динамической - в зависимости от области видимости указателя. Но глобальная/локальная память - это другое. В старой винде было такое понятие. Локальная - это память сегмента, принадлежащего приложению или библиотеке и адресуемая ближним указателем, а глобальная - вся остальная память, в том чсисле память системы. Чарлз Петзолд. Программирование для Windows 95. Том 2. Исходя из такого понимания глобальности/локальности, проанализируй вид памяти современной винды. Какова разрядность указателя? 32 бита и больше? Тогда он дальний, значит не ближний. Значит память не локальная. Значит глобальная. Но сейчас это не вид памяти, так как нет других её видов в той же классификации. Глобальная - устаревший эпитет, прилепившийся ко всей памяти, какая осталась ещё с тех времён, когда было два её вида.
&quot писал(а):Динамическая память. Из плюсов: самая гибкая память, выделить можно столько, сколько решили во время работы программы, жить объект будет вне зависимости от того в каких скобках он родился, очистить можно насильно до завершения программы. Из минусов: очень медленно выделение. Если злоупотреблять new/delete то это может стать настоящим ударом по производительности программы.
Если её применение уместно, то результат будет положителен. В том числе, выиграешь и в скорости счёта.
&quot писал(а):Статическая память: казалось здесь одни плюсы. Время выделения нулевое, время жизни - пока работает программа.
Лично я туда пихаю только те переменные, которые:
1. должны жить дольше одного вызова функции, которая к этим данным обращзается, или нужны более, чем одной функции,
2. занимают не более 400 байт каждая (считая любой массив одной переменной),
3. не имеют явно динамический тип (не являются, например, деревьями).
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

&quot писал(а):Насколько я знаю, все переменные, которые c++ размещает в автоматической памяти в других языках называются локальными
Они и в С++ называются локальными. Локальные переменные располагаются в автоматической (стековой) памяти.
&quot писал(а):В старой винде было такое понятие. Локальная - это память сегмента, принадлежащего приложению или библиотеке и адресуемая ближним указателем, а глобальная - вся остальная память, в том чсисле память системы.
Дела давно минувших дней, преданья старины глубокой... Во-первых, зачем вспоминать старую Винду, мы работаем сегодня, а не 15 лет назад. Во-вторых, это было не на Винде, а ещё в ДОС и Win 3.x (которую я не отношу к Винде). В-третьих, я не уверен, что ты используешь верную терминологию. Раньше было понятия дальней и ближней адресации. Является ли адресуемая ближней адресацией память "локальной", не могу сказать, но я такого термина не слышал ни разу. Даже если так, зачем ты сейчас об этом заговорил, если сейчас все поинтеры являются "дальними". Ну и в-четвертых, мне становится вообще удивительно как ты представлял себе раньше возвращение значения функцией, если в понятия локальной и глобальной памяти вкладывал ближнюю и дальнюю адресацию.
&quot писал(а):В том числе, выиграешь и в скорости счёта.
В скорости счёта чего я выиграю? Каким образом скорость доступа (если я правильно понял) памяти коррелирует с её типом?
&quot писал(а):Исходя из такого понимания глобальности/локальности, проанализируй вид памяти современной винды. Какова разрядность указателя? 32 бита и больше? Тогда он дальний, значит не ближний. Значит память не локальная. Значит глобальная. Но сейчас это не вид памяти, так как нет других её видов в той же классификации. Глобальная - устаревший эпитет, прилепившийся ко всей памяти, какая осталась ещё с тех времён, когда было два её вида.
Как по-мне, так это ничто иное, как нелепые объяснения своего неумения донести мысль и своих пробелов в понимании сути происходящего. Я один это заметил? :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

&quot писал(а):не на Винде, а ещё в ДОС и Win 3.x (которую я не отношу к Винде).
Win 3.x разве не windows? Ещё не система, но слово в названии уже Windows.
&quot писал(а):понятия дальней и ближней адресации
Это в DOS, а в Win 3.x функции, работавшие с памятью, имели в качестве части имени LOCAL и GLOBAL и всё что LOCAL было NEAR, а всё, что GLOBAL - FAR.
&quot писал(а):как ты представлял себе раньше возвращение значения функцией, если в понятия локальной и глобальной памяти вкладывал ближнюю и дальнюю адресацию.
А причём здесь это? Локальная/глобальная память это одно, а локальные/глобальные данные - другое. Смыслы прилагательных на самом деле различны. Я просто хотел как короче. Думал, что раз паямть сейчас вся глобальная, то отнесут прилагательные не кней, а к переменным.
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
&quot писал(а):В скорости счёта чего я выиграю? Каким образом скорость доступа (если я правильно понял) памяти коррелирует с её типом?
Ты один раз выделеил много, но не сверх всякой меры, динамической памяти, а потом много раз быстро к ней обращаешься. Тормозов мало. Другой вариант. Тебе наждо много памяти, но сколько именно ты не знаешь. А при статическом выделении надо сразу указать, сколько надо. Выделяешь с запасом столько, что выходишь за пределы физической паямти. Где вся эта память реально окажется? На винчестере. А обращения к нему происходят медленнее, чем к физической оперативной памяти, пусть даже и динамической.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

&quot писал(а):Ты один раз выделеил много, но не сверх всякой меры, динамической памяти, а потом много раз быстро к ней обращаешься. Тормозов мало.
Если я выделил один раз, значит я знал сколько нужно выделять с самого начала. Тогда я могу выделить ровно столько же статической памяти не теряя на времени выделения.

Ты мне так и не сказал где здесь скорость счёта?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

&quot писал(а):Если я выделил один раз, значит я знал сколько нужно выделять с самого начала. Тогда я могу выделить ровно столько же статической памяти не теряя на времени выделения.
С самого начала, это когда? На этапе разработки? Или исполнения?
А скоростью счёта иногда называют характеристику производительности программы в отличие от быстродействия - характеристики производительности компьютера. Скорость счёта тем выше, чем:
1. лучше алгоритм,
2. быстрее доступ к памяти,
3. выше быстродействие.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Ответить