реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Возвращение указателя на динамический массив
Nikitoc
сообщение Mar 1 2012, 15:03
Сообщение #1


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Всем привет!
Вопросик простой, но для полноты картины происходящего в компиляторе (или в МК) мне нужно этот вопрос разъяснить. Допустим, есть какая-то функция:
Код
WORD *Multiple (BYTE A, BYTE B){
           WORD *result;
           result = (WORD *)malloc(1);
           *result = A * B;
           return result;
       }


Собственно вопросы:

1. Где необходимо удалять эту переменную result (я имею в виду вызов ф-ции free())? Только в той функции, в которой она была выделена (Multiple()) или же можно сделать это в вызывающей функции по полученному указателю?
2. Я правильно понимаю, что возвращать указатель можно потому, что динамически выделенная переменная помещается в кучу, а не в стек?
3. Как называется область оперативной памяти, которая не отводится под кучу или стек? Как она используется компилятором (что туда "ложится")?
Go to the top of the page
 
+Quote Post
ys05
сообщение Mar 1 2012, 15:59
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 47
Регистрация: 20-10-11
Пользователь №: 67 864



Цитата(Nikitoc @ Mar 1 2012, 18:03) *
1. Где необходимо удалять эту переменную result (я имею в виду вызов ф-ции free())? Только в той функции, в которой она была выделена (Multiple()) или же можно сделать это в вызывающей функции по полученному указателю?
2. Я правильно понимаю, что возвращать указатель можно потому, что динамически выделенная переменная помещается в кучу, а не в стек?
3. Как называется область оперативной памяти, которая не отводится под кучу или стек? Как она используется компилятором (что туда "ложится")?

1. free можно вызывать в вызывающей функции и в другой функции и т.д.
2. да, правильно, куча от стека не зависит
3. вообще обычно под стек память резервируется конкретно, а под рост кучи остается вся остальная; хотя может где-то и по другому
Go to the top of the page
 
+Quote Post
toweroff
сообщение Mar 1 2012, 16:09
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



ойой
возвращать из функции адрес локальной переменной... help.gif
Go to the top of the page
 
+Quote Post
xemul
сообщение Mar 1 2012, 16:20
Сообщение #4



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(toweroff @ Mar 1 2012, 20:09) *
ойой
возвращать из функции адрес локальной переменной...

Возвращается адрес блока, выделенного malloc(). Если у ТС есть охота на траблы, почему бы и нет?
Go to the top of the page
 
+Quote Post
toweroff
сообщение Mar 1 2012, 16:40
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(xemul @ Mar 1 2012, 20:20) *
Возвращается адрес блока, выделенного malloc()

да не суть laughing.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 1 2012, 18:18
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Nikitoc @ Mar 1 2012, 17:03) *
1. Где необходимо удалять эту переменную result (я имею в виду вызов ф-ции free())? Только в той функции, в которой она была выделена (Multiple()) или же можно сделать это в вызывающей функции по полученному указателю?
В том месте, где вам больше не нужна та память, на которую указывает указатель. Совершенно не обязательно в этой функции. Вся информация, необходимая для освобождения памяти хранится в скрытом виде внутри выделенного malloc() блока и для доступа к ней достаточно лишь указателя, который вернул malloc().
По второму вопросу: совершенно верно.
QUOTE (Nikitoc @ Mar 1 2012, 17:03) *
3. Как называется область оперативной памяти, которая не отводится под кучу или стек? Как она используется компилятором (что туда "ложится")?
Никак не используется. Поэтому либо под стек выделяют всю оставшуюся после резервирования кучи память либо наоборот - под кучу всю оставшуюся после резервирования стека.

QUOTE (xemul @ Mar 1 2012, 18:20) *
Возвращается адрес блока, выделенного malloc(). Если у ТС есть охота на траблы, почему бы и нет?
Какие траблы вы имеете ввиду? И как вы себе представляете другое использование кучи?

QUOTE (toweroff @ Mar 1 2012, 18:40) *
да не суть laughing.gif
Именно что суть. Да вы не стесняйтесь, расскажите нам в чем тут ойой. Посмеемся вместе. Над вами.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
toweroff
сообщение Mar 1 2012, 18:28
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(Сергей Борщ @ Mar 1 2012, 22:18) *
Именно что суть

кучу использую крайне редко
отсюда и у меня некоторое, возможно, непонимание использования оной
то есть malloc просматривает при выделении нужную "дырку", в не зависимости, как и где вызван запрос на область памяти?
посему - free освобождает этот кусок, образуя дырку?
и без разницы где это вызывается?
также, выделяя/освобождая как попало куски памяти, получаем вариант, когда суммарно память свободная есть, а выделить ее не можем, потому как нет одной дырки подходящего размера?

Цитата(Сергей Борщ @ Mar 1 2012, 22:18) *
Посмеемся вместе. Над вами.

валяйте
Go to the top of the page
 
+Quote Post
xemul
сообщение Mar 1 2012, 18:54
Сообщение #8



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Сергей Борщ @ Mar 1 2012, 22:18) *
Какие траблы вы имеете ввиду? И как вы себе представляете другое использование кучи?

Я не про использование кучи - оно вполне естественно, - а про несвязанные явно выделение и освобождение памяти.
Мне больше по душе, когда "выделил - ... - освободил" очевидно (свернув промежуточные {} при необходимости). Мне и своего склероза памяти хватает sm.gif
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение Mar 1 2012, 18:54
Сообщение #9


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Всем спасибо за ответы. Вопрос Сергею: я спросил про "неназванную" область оперативной памяти (которая не куча и не стек) потому что столкнулся с этим при работе в Keil uVision (я пишу под Cortex-M3, хотя это наверное не важно). В стартаповом файле конфигурируется куча и стек. Из доступных 16кБ я под стек выделил 1кБ, а куче ничего, т.к. не использую динамического выделения памяти в этом проекте. Так вот, в программе у меня определены два буфера по 4кБ (как глобальные переменные). Получается, что расположены эти два буфера не в стеке (слишком мал) и не в куче (т.к. они определены статически да и под кучу памяти не выделено). Я, конечно, понимаю, что частично ответил на свой вопрос, но все равно хочется больше информации в этом направлении. Может быть управление оперативной памятью зависит от платформы (компилятора)?
Go to the top of the page
 
+Quote Post
_Ivana
сообщение Mar 1 2012, 19:39
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710



Это стОит того, чтобы ждать! sm.gif
Так и я пойму даже кое-что про ОЗУ. Хотя, если объем статических переменных ограничен по определению, кучу и стек мы тоже ограничиваем - остальное просто не используется? Тогда хорошо бы что-то (либо кучу либо стек) не ограничивать и использовать на весь оставшийся объем памяти. Просто мысли дилетанта sm.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 1 2012, 19:44
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (toweroff @ Mar 1 2012, 20:28) *
то есть malloc просматривает при выделении нужную "дырку", в не зависимости, как и где вызван запрос на область памяти?
посему - free освобождает этот кусок, образуя дырку?
Существует множество реализаций менеджеров памяти со своими преимуществами и недостатками. Для понимания их работы можно рассмотреть простейший случай. Куча - отдельный зарезервированный участок памяти. При старте - она одна большая "дырка". При вызове malloc() из нее "откусываются" кусочки запрошенного размера плюс еще немного для служебной информации. При вызове free() эти кусочки становятся небольшими "дырками", а если они с какой-либо стороны соприкасаются с другой "дыркой" - то эти две дырки объединяются в одну "дырку" суммарного размера. Таким образом, если освободить все выделенные malloc() переменные - будет снова одна большая "дырка".
QUOTE (toweroff @ Mar 1 2012, 20:28) *
и без разницы где это вызывается?
Да, естественно. malloc возвращает указатель на "откушенный" участок. Грубо говоря указывать вы можете откуда угодно, пока указываете в это место.
QUOTE (toweroff @ Mar 1 2012, 20:28) *
также, выделяя/освобождая как попало куски памяти, получаем вариант, когда суммарно память свободная есть, а выделить ее не можем, потому как нет одной дырки подходящего размера?
Совершенно верно. Это называется фрагментацией кучи и является главным ее недостатком. Именно из-за нее и стараются не использовать динамические переменные в контроллерах. В основном именно для борьбы с ней и существуют различные менеджеры памяти.
QUOTE (toweroff @ Mar 1 2012, 20:28) *
валяйте
В этой функции не возвращается адрес локальной переменной. Локальная переменная тут одна - result и возвращается ее значение. А вот значение ее является указателем на какую-то точку глобальной кучи (адресом). Так что не ойой, а хихи 08.gif . Ваш ход.
QUOTE (xemul @ Mar 1 2012, 20:54) *
Мне больше по душе, когда "выделил - ... - освободил" очевидно (свернув промежуточные {} при необходимости). Мне и своего склероза памяти хватает sm.gif
А, в этом смысле... Ну тогда все объектно-ориентированное придется отменить.
QUOTE (Nikitoc @ Mar 1 2012, 20:54) *
я спросил про "неназванную" область оперативной памяти (которая не куча и не стек) потому что столкнулся с этим при работе в Keil uVision
А, понял. Глобальные переменные размещаются в первую очередь. А уже что осталось от ОЗУ после них - отдается под стек и кучу. Ну а что и они не использовали - висит без пользы и вносит вклад в глобальное потепление.
QUOTE (Nikitoc @ Mar 1 2012, 20:54) *
Получается, что расположены эти два буфера не в стеке
Переменные бывают:
- глобальные ("видны" во всем проекте, хранят значения от старта до завершения программы)
- глобальные статические ("видны" в пределах единицы компиляции, хранят значения от старта до завершения программы)
- локальные статические ("видны" от точки объявления до конца блока, хранят значения от старта до завершения программы)
- локальные автоматические("видны" от точки объявления до конца блока, хранят значения от точки объявления до конца блока).
- динамические (создаются по malloc(), new(), уничтожаются по free(), delete()).
вроде бы ничего не забыл.
Первые три хранятся в памяти в той самой области, которая резервируется под них в первую очередь. И размер этой области линкер может легко подсчитать - это суммарный размер переменных плюс (при необходимости) некоторое количество "пропусков" для выравнивания адресов переменных. Под четвертые память выделяется на стеке в процессе работы. Под пятые память выделяется в куче.
QUOTE (Nikitoc @ Mar 1 2012, 20:54) *
(слишком мал)
Если стека не хватит - вы узнаете об этом только в процессе работы программы. Ибо расчитать расход стека очень сложно, а иногда и невозможно. Поэтому компилятор/линкер его не считает. Вы резервируете N байт, линкер их размещает. Но ни компилятор, ни линкер не скажут, что этих N байт не хватает для всех ваших локальных автоматических переменных, адресов возврата, контекста прерываний и т.п. Поэтому когда вашим данным не хватит места на стеке, они начнут налезать на данные соседней области - незанятой памяти, кучи, глобальных переменных. Тогда и начнутся чудеса.

QUOTE (_Ivana @ Mar 1 2012, 21:39) *
Тогда хорошо бы что-то (либо кучу либо стек) не ограничивать и использовать на весь оставшийся объем памяти. Просто мысли дилетанта sm.gif
Да, так и делают. Чаще стек, ибо просчитать его сложно, пусть уж растет сколько может. А когда налезет на другие данные - надо будет переписывать программу, ибо памяти взять уже ну неоткуда совсем.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
toweroff
сообщение Mar 1 2012, 19:51
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(Сергей Борщ @ Mar 1 2012, 23:44) *
В основном именно для борьбы с ней и существуют различные менеджеры памяти.
В этой функции не возвращается адрес локальной переменной. Возвращается указатель на какую-то точку глобальной кучи

получается, что информация о куче хранится в какой-то реализации связанного списка там же, в области кучи (ну пока другого варианта не вижу)
отсюда и сложность в использовании оной?
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение Mar 1 2012, 19:57
Сообщение #13


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Сергей, спасибо Вам большое. Разжевано предельно понятно cheers.gif Систематизация - полезная штука.
Go to the top of the page
 
+Quote Post
_Ivana
сообщение Mar 1 2012, 20:00
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710



Со стеком имхо ничего не поможет справиться, кроме методов программирования, его минимизирующих. Ограничить стек или не ограничить - все равно если он вылезет за пределы допустимого и налезет на нужную область - то будут действительно чудеса sm.gif
А в asm нет "статических" и "динамических". Но все asm программисты расписывают имеющееся ОЗУ и сами знают, что им надо хранить от начала и до конца, а какие области можно переписывать в результате промежуточных операций. Си и конкретно менеджеры памяти просто берут эту трудоемкую работу на себя. Но даже на asm есть стек, и при многих уровнях вложенных прерываний он тоже весьма сложно прогнозируется...
Go to the top of the page
 
+Quote Post
toweroff
сообщение Mar 1 2012, 20:03
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(_Ivana @ Mar 2 2012, 00:00) *
Со стеком имхо ничего не поможет справиться, кроме методов программирования, его минимизирующих. Ограничить стек или не ограничить - все равно если он вылезет за пределы допустимого и налезет на нужную область - то будут действительно чудеса sm.gif
А в asm нет "статических" и "динамических". Но все asm программисты расписывают имеющееся ОЗУ и сами знают, что им надо хранить от начала и до конца, а какие области можно переписывать в результате промежуточных операций. Си и конкретно менеджеры памяти просто берут эту трудоемкую работу на себя. Но даже на asm есть стек, и при многих уровнях вложенных прерываний он тоже весьма сложно прогнозируется...

почему?
и на С то же самое... все можно сделать и в статике, как я понимаю. Остальные механизмы - удобства для. Но все имеет свой гемор
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 03:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01503 секунд с 7
ELECTRONIX ©2004-2016