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

 
 
> возврат указателя на массив из ф-ии, немного теории
Метценгерштейн
сообщение Jun 6 2017, 07:41
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



Есть ф-я, где локально объявлен некий массив. И я возвращаю указатель на этот массив. Смущает, что он локальный и на стеке. Он вернется в вызывающую ф-ю? Ничего по пути не потеряется?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AnatolyT
сообщение Jun 8 2017, 19:56
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 176
Регистрация: 29-03-10
Пользователь №: 56 269



Не стоит рассчитывать на сохранность локальных переменных вне функции. Поступаю следующим образом, определяю область памяти с помощью malloc() и передаю указатель в функцию, которая в свою очередь тоже может передать и возвратить его, после возврата указателя освобождаю область с помощью free().
Go to the top of the page
 
+Quote Post
one_eight_seven
сообщение Jun 8 2017, 22:11
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 916
Регистрация: 3-10-08
Из: Москва
Пользователь №: 40 664



Цитата(AnatolyT @ Jun 8 2017, 22:56) *
Не стоит рассчитывать на сохранность локальных переменных вне функции. Поступаю следующим образом, определяю область памяти с помощью malloc() и передаю указатель в функцию, которая в свою очередь тоже может передать и возвратить его, после возврата указателя освобождаю область с помощью free().

Откровенно странный способ, ваш компилятор не поддерживает С11 или C99?

Сообщение отредактировал one_eight_seven - Jun 8 2017, 22:12
Go to the top of the page
 
+Quote Post
conan
сообщение Jun 9 2017, 00:34
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 3-11-11
Пользователь №: 68 126



Цитата(one_eight_seven @ Jun 9 2017, 01:11) *
Откровенно странный способ, ваш компилятор не поддерживает С11 или C99?

Почему странный? Стандартный способ.
Два основных подхода:
1. Вызывающая сторона выделяет память и передает адрес буфера в функцию в качестве аргумента. Функция заполняет буфер результатом работы. За освобождение памяти отвечает вызывающая сторона. Иногда, когда заранее неизвестно сколько надо будет памяти, чтобы поместился результат, функция вызывается два раза. Первый раз -- с 0 в качестве указателя на буфер и тогда, функция не генерирует результат, а только вычисляет и возвращает размер необходимого буфера. Потом вызывающая сторона готовит буфер нужного размера и вызывает функцию повторно, но уже с указателем на буфер. Такой под-подход встречается, например, в WinAPI.
2. Память выделяет сама функция и возвращает указатель на этот блок, заполненный результатом работы. Не кошерно, если потом память освобождается прямым вызовом free. По-хорошему должна быть отдельная функция которая просто освобождает память:
Data *doSomething();
void free(Data *);
Именно так устроено большинство C-библиотек. Есть набор функций, которые выделяют память и возвращают указатель и есть отдельная функция, которая по этим указателям память освобождает. Такой подход, например, позволяет подключать библиотеки, которые собраны другим компилятором (или тем же, но с другими настройками, которые влияют на распределитель памяти)

Go to the top of the page
 
+Quote Post
one_eight_seven
сообщение Jun 9 2017, 06:54
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 916
Регистрация: 3-10-08
Из: Москва
Пользователь №: 40 664



Цитата(conan @ Jun 9 2017, 03:34) *
Почему странный? Стандартный способ.
Два основных подхода:
1. Вызывающая сторона выделяет память и передает адрес буфера в функцию в качестве аргумента. Функция заполняет буфер результатом работы. За освобождение памяти отвечает вызывающая сторона. Иногда, когда заранее неизвестно сколько надо будет памяти, чтобы поместился результат, функция вызывается два раза. Первый раз -- с 0 в качестве указателя на буфер и тогда, функция не генерирует результат, а только вычисляет и возвращает размер необходимого буфера. Потом вызывающая сторона готовит буфер нужного размера и вызывает функцию повторно, но уже с указателем на буфер. Такой под-подход встречается, например, в WinAPI.
2. Память выделяет сама функция и возвращает указатель на этот блок, заполненный результатом работы. Не кошерно, если потом память освобождается прямым вызовом free. По-хорошему должна быть отдельная функция которая просто освобождает память:
Data *doSomething();
void free(Data *);
Именно так устроено большинство C-библиотек. Есть набор функций, которые выделяют память и возвращают указатель и есть отдельная функция, которая по этим указателям память освобождает. Такой подход, например, позволяет подключать библиотеки, которые собраны другим компилятором (или тем же, но с другими настройками, которые влияют на распределитель памяти)

Conan, этот метод стандартный для C89. Если на момент вызова функции, которая должна только заполнить буфер, размер буфера уже известен, а у вас в пункте 1 так, то с этим в C99/С11 прекрасно справляется автоматическая модель памяти, нет нужды рисковать с использованием ручного управления памятью.
Я понимаю, что лучший инструмент - это не тот, который лучше, а тот, который вы знаете, и это нормально. Но советовать такое в 2017 - это ретроградство, и даже немножко вредительство, насколько мне изветсно, даже Будда терял самообладание, когда ему приходилось пользоваться malloc'ом.

По пункту 2. Врапперы вокруг free и malloc полностью поддерживаю там, где без malloc и free не обойтись. Но в полседнее время мало встречаю необходимости в malloc. А вот free нужна гораздо чаще.

Как по мне, malloc нужен там, где потом будет использоваться realloc, но, повторюсь, нужды в этом сейчас куда меньше, чем об этом написано в книжках 80-х и 90-х годов.

P.S. Не знаком с WinApi, но Win в начале позволяет говорить о том, что это microsoft'овское, а у них компилятор не поддерживает C99/C11. По крайней мере, отказ о поддержке этих стандартов языка был официально объявлен, когда я последний раз рассматривал возможность прикоснуться к Visual Studio.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Метценгерштейн   возврат указателя на массив из ф-ии   Jun 6 2017, 07:41
- - AlexandrY   Цитата(Метценгерштейн @ Jun 6 2017, 10:41...   Jun 6 2017, 07:49
|- - jcxz   Цитата(AlexandrY @ Jun 6 2017, 09:49) Ну ...   Jun 6 2017, 08:40
- - ViKo   Когда вернулись из функции, ее локального массива ...   Jun 6 2017, 08:00
- - Метценгерштейн   ну а без шуток? Получается, что массив удаляется. ...   Jun 6 2017, 08:11
|- - megajohn   Цитата(Метценгерштейн @ Jun 6 2017, 11:11...   Jun 6 2017, 08:43
- - Метценгерштейн   Профессионал- тот, кто не стесняется озвучить непо...   Jun 6 2017, 08:58
|- - megajohn   Цитата(Метценгерштейн @ Jun 6 2017, 11:58...   Jun 6 2017, 09:08
- - sigmaN   Голосую за то, что это просто толстый троллинг.   Jun 6 2017, 10:25
|- - demiurg_spb   Цитата(sigmaN @ Jun 6 2017, 13:25) Не ина...   Jun 6 2017, 10:38
- - conan   С точки зрения спецификации языка C доступ к локал...   Jun 8 2017, 19:35
|- - k155la3   Цитата(AnatolyT @ Jun 8 2017, 22:56) Не с...   Jun 9 2017, 08:18
|- - novikovfb   Цитата(k155la3 @ Jun 9 2017, 12:18) Вмест...   Jun 9 2017, 08:41
- - sigmaN   В функции winAPI совершенно не обязательно передав...   Jun 9 2017, 09:11
- - one_eight_seven   ЦитатаПри чем тут С11/C99???? Во-первых, они позво...   Jun 9 2017, 11:00
- - sigmaN   ЦитатаВо-первых, они позволяют создавать массивы, ...   Jun 9 2017, 11:08
- - one_eight_seven   ЦитатаК топику это как-то относится? )))) Если всё...   Jun 9 2017, 12:26
|- - jcxz   Цитата(one_eight_seven @ Jun 9 2017, 14:2...   Jun 12 2017, 07:01
|- - novikovfb   Цитата(jcxz @ Jun 12 2017, 11:01) И каким...   Jun 12 2017, 15:22
- - sigmaN   ЦитатаИ в чём проблема что на стеке? Вы использует...   Jun 12 2017, 09:18


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

 


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


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