Перейти к содержанию
    

возврат указателя на массив из ф-ии

Есть ф-я, где локально объявлен некий массив. И я возвращаю указатель на этот массив. Смущает, что он локальный и на стеке. Он вернется в вызывающую ф-ю? Ничего по пути не потеряется?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть ф-я, где локально объявлен некий массив. И я возвращаю указатель на этот массив. Смущает, что он локальный и на стеке. Он вернется в вызывающую ф-ю? Ничего по пути не потеряется?

Ну судя по тому что вы профессионал, то знаете что делаете.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда вернулись из функции, ее локального массива уже нет, если он не статический. Возвращать указатель на ничто? Только профессионалу позволено, потому что реально массив все еще плехается где-то в ОЗУ. :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну а без шуток?

Получается, что массив удаляется. Разве что может повезти, и он еще не успел затереться в ОЗУ?

И по- хорошему, так нельзя делать.

Верно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну судя по тому что вы профессионал, то знаете что делаете.

Да - профессионал в написании сообщений в форуме :biggrin:

 

Человека, делающего подобное:

Есть ф-я, где локально объявлен некий массив. И я возвращаю указатель на этот массив. Смущает, что он локальный и на стеке.

не то что профессионалом, а и просто знающим - язык не поворачивается назвать... :smile3046:

 

И по- хорошему, так нельзя делать.

Если хотите заложить сюрпризов в ПО, чтобы насолить работодателю, уволившему Вас с работы, то можно.

 

Чтобы вернуть некое содержимое из функции на стеке (в автоматической памяти), обычно такой массив создаётся в вызывающей функции и указатель передаётся в вызываемую.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну а без шуток?

Получается, что массив удаляется. Разве что может повезти, и он еще не успел затереться в ОЗУ?

 

да пройдись в дизасме, и все увидишь.

 

должно быть примерно так:

перед вызовом функции StackPointer = 1000

StackPointer уменьшается на 100 и стал 900 ( 100 это сколько нужно для размещения твоего массива, прочего ( используемые регистры тоже будут сохранены в стек ) в процессе работы функции )

по выходу из функции StackPointer + 100 и равен 1000

дальнейшие команды могу похерить твой массив, а могут и не похерить - но никто специально не стирает

 

p.s. если функция1 вызывает функцию2 а она вызывает функцию3 то компилятор, может единожды сделать StackPointer "туды/сюды", а не трижды

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Профессионал- тот, кто не стесняется озвучить непонятный для него момент, пытается закрыть этот вопрос.

Ламер- тот, который пишет как умеет, не пытается задать неудобный вопрос, боится, что его начнут поливать. И код у него соответствующий.

А кто каждый из нас- определяем сами.

За ответы- спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

За ответы- спасибо.

 

такая реакция у публики, потому что это азы

вот "Язык программирования Си" Брайан Керниган, Деннис Ритчи

Каждая локальная переменная функции возникает только в момент обращения к этой функции и исчезает после выхода из нее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С точки зрения спецификации языка C доступ к локальным переменным функции после её завершения влечет неопределенное поведение. Если копнуть глубже, то поведение зависит от устройства конкретного компилятора и конкретной платформы. На микроконтроллерах и ОС типа DOS данные в локальном массиве после завершения функции могут быть перезаписаны обработчиками аппаратных прерываний. В ОС использующих механизм страничной адресации памяти диапазон массива теоретически вообще может оказаться unmap-ленными и тогда даже попытка чтения приведет к segmenation fault и немедленному завершению программы

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Почему странный? Стандартный способ.

Два основных подхода:

1. Вызывающая сторона выделяет память и передает адрес буфера в функцию в качестве аргумента. Функция заполняет буфер результатом работы. За освобождение памяти отвечает вызывающая сторона. Иногда, когда заранее неизвестно сколько надо будет памяти, чтобы поместился результат, функция вызывается два раза. Первый раз -- с 0 в качестве указателя на буфер и тогда, функция не генерирует результат, а только вычисляет и возвращает размер необходимого буфера. Потом вызывающая сторона готовит буфер нужного размера и вызывает функцию повторно, но уже с указателем на буфер. Такой под-подход встречается, например, в WinAPI.

2. Память выделяет сама функция и возвращает указатель на этот блок, заполненный результатом работы. Не кошерно, если потом память освобождается прямым вызовом free. По-хорошему должна быть отдельная функция которая просто освобождает память:

Data *doSomething();

void free(Data *);

Именно так устроено большинство C-библиотек. Есть набор функций, которые выделяют память и возвращают указатель и есть отдельная функция, которая по этим указателям память освобождает. Такой подход, например, позволяет подключать библиотеки, которые собраны другим компилятором (или тем же, но с другими настройками, которые влияют на распределитель памяти)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему странный? Стандартный способ.

Два основных подхода:

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.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...