Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Возврат строки неизвестного размера из функции, работа с выделением памяти в функции 
V
    Опции темы
ama_kid
Дата 6.6.2008, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Доброго всем времени суток...

Сразу скажу, что при написании топика почитал эту и эту тему, выданные мне форумом как "похожие темы", ответы там не сильно помогли, поиском тоже пользовался - не айс...  между тем вопрос по большому счету не стОит и того количества букв, которые я тут напишу, но тем не менее, постараюсь в красках и примерах на пальцах объяснить суть ментального геморроя...
Итак, недавно пришлось переводить кое-какой код с Дельфи на С++ и столкнулся с интересной для себя теоретической проблемой, которая подспудно грызла меня давно, но как-то не было случая с ней основательно разобраться... Дело в том, что есть, допустим, гипотетический код на дельфи:
Код
function GetString:string;
var 
 s:string;
begin
  s:=...    // Здесь, к примеру, динамическое 
  s:=s+... // формирование строки по какому-то алогритму
  Result:=s; {...some dynamic string...} ;
end;
Как видно из этого примера - размер возвращаемой строки заранее неизвестен, компилятор автоматически выделяет в стеке необходимый буфер под строку, расширяя по необходимости, и затем возвращает её... Теперь пытаюсь сделать то же самое на С++:
Код
char * GetString(void)
{
  char *s;
  ...  // Здесь я использую необходимые new\malloc\realloc\strcpy\strcat для 
  ...  // получения необходимого количества памяти и формирования строки.
  return s; // В итоге - s содержит необходимую мне строку.
}
Возникают следующие вопросы:
1) Очевидно, что если я оставлю функцию в таком виде - я гарантирую себе весёлую жизнь с утечками памяти, ибо delete\free нигде не вызываются и память по выходу из функции утекает. В итоге - закономерный вопрос: где необходимо освобождать память? Выделять память до вызова функции нет смысла, ибо размер буфера неизвестен; освобождать внутри функции - бессмысленно; выделять внутри, а освобождать после выхода - некрасиво (и есть небезосновательное подозрение, что неправильно)...
2) Как вообще правильно действовать в таких случаях? Использование разнообразных классов типа std::string не предлагать, сам знаю, что они для этого и предназначены, но так же помню, что разнообразные библиотечные функции, работающие с char * - работают вполне корректно и возвращают указатели на вполне валидные буферы. Да, я понимаю, что там используется несколько другой подход - передаются указатели на буферы, где необходимо разместить ответ, но не до конца понимаю, где происходит выделение памяти под эти буферы? (Тот же strcpy - как и где выделяет память под char *strDestination?). Единственный более-менее внятный ответ на похожий вопрос от _hunter'а я увидел у RAN, но и там возник вопрос: а что если память под параметр char* param выделена не через new, а допустим, через malloc (при условии, что я не знаю точно)?

В общем, буду признателен, если помимо ответов "ха-ха, ты далпайоп!" и "кури маны, дятел!" (как любит говорить мне мой друг) будут более содержательные разъяснения smile


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Fazil6
Дата 6.6.2008, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(ama_kid @  6.6.2008,  10:13 Найти цитируемый пост)
Как вообще правильно действовать в таких случаях?

ну если посмотреть апишные функции, то как правило им передаётся буфер и размер, а они возвращают количество записанных символов и, если что, количество символов, которые не влезли.
По большому счету мне непонятны твои сомнения относительно new или malloc. Ведь полюбому буфер надо выделять перед вызовом и функции  побарабану как он получен (хоть массив в стеке). Возвращать из функции имеет смысл если возвращается const char* заранее определененый, а в твоем случае нужно подготовленный буфер передавать и заполнять его.

Добавлено через 5 минут и 2 секунды
если смотреть твой код
Код

char * GetString(void)
{
  char *s;
  ...  // Здесь я использую необходимые new\malloc\realloc\strcpy\strcat для 
  ...  // получения необходимого количества памяти и формирования строки.
  return s; // В итоге - s содержит необходимую мне строку.
}

неправильно это. Плохо делать выделение памяти внутри функции. Так ты делаешь вызывающий код зависимым от реализации этой функции. 
PM MAIL   Вверх
Walker
Дата 6.6.2008, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 363
Регистрация: 23.10.2006

Репутация: 1
Всего: 16



Хоть сам ещё нахожусь в процессе познания, принять участие в обсуждении интересно. Может вместе найдём истину. smile 
Сразу оговорюсь, я работаю исключительно с С.
На первый взгляд складывается ощущение, что при грамотном проектировании такой ситуации возникать просто не должно.
Цитата

выделять внутри, а освобождать после выхода - некрасиво (и есть небезосновательное подозрение, что неправильно)...

Правильно понимаете. Это чревато следующей ошибкой, которая ловится, зачастую только под отладчиком. Если Вы передаёте адрес как аргумент, то работаете с локальной копией указателя, и внешний мир ничего не знает о выделенном участке. Это будет бесцельная трата памяти. Если же вы используете адрес в качестве возвращаемого значения, то аргументом передавайте размер, Ваша функция будет выполнять роль оболочки над malloc. Напишите обратную функцию - оболочку над free.
Библиотечные функции и strcpy в том числе используют именно преопределённые буферы, за выделение и освобождение которых отвечаете Вы.
Попробуйте представить иной пример, тогда найдём в открытых исходниках аналог и разберёмся. Пока я такого не встречал. smile 

PS Пока инет глючил, Fazil6 опередил.smile

Это сообщение отредактировал(а) Walker - 6.6.2008, 10:54


--------------------
"От вчерашних побед остаётся усталость, если завтрашний день не сулит ничего..."
PM MAIL   Вверх
Fazil6
Дата 6.6.2008, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



как вариант сначала запрашивать размер буфера, а потом выделять буфер и вызывать GetString, но честно говоря я бы так не делал. 
По любому используя С++ лучше контейнер (стандартный или самодельный) вместо char* 
PM MAIL   Вверх
Mayk
Дата 6.6.2008, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(ama_kid @  6.6.2008,  14:13 Найти цитируемый пост)
Тот же strcpy - как и где выделяет память под char *strDestination

strcpy не выделяет память. Выделение памяти - это проблемы вызывающего  strcpy кода.

Цитата(ama_kid @  6.6.2008,  14:13 Найти цитируемый пост)

В общем, буду признателен, если помимо ответов "ха-ха, ты далпайоп!" и "кури маны, дятел!" (как любит говорить мне мой друг) будут более содержательные разъяснения

курить std::string (c++)
и realloc  ©


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Fazil6
Дата 6.6.2008, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(ama_kid @  6.6.2008,  10:13 Найти цитируемый пост)
Да, я понимаю, что там используется несколько другой подход - передаются указатели на буферы, где необходимо разместить ответ, но не до конца понимаю, где происходит выделение памяти под эти буферы? (Тот же strcpy - как и где выделяет память под char *strDestination?).


вот те раз... приехали... нигде он ее не выделяет. Оба буфера выделены до вызова. 
PM MAIL   Вверх
Mayk
Дата 6.6.2008, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(ama_kid @  6.6.2008,  14:13 Найти цитируемый пост)
Выделять память до вызова функции нет смысла, ибо размер буфера неизвестен

realloc курить сюда.

зы! опять мои посты не склеились >ОДНАКО<

Это сообщение отредактировал(а) Mayk - 6.6.2008, 10:56


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Andrey44
Дата 6.6.2008, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 2
Всего: 26



А можно ли вообще возвращать адрес локальной переменной?
Компилятор по-этому поводу предупреждает!


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
ama_kid
Дата 6.6.2008, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Fazil6 @  6.6.2008,  10:51 Найти цитируемый пост)
используя С++ лучше контейнер (стандартный или самодельный) вместо char*
Оно, конечно, может и лучше, но... фиг знает, иногда бывает необходимо и на чистом С писать, а тогда иметь на вооружении знания о работе с char* оказывается полезным...
Цитата(Fazil6 @  6.6.2008,  10:37 Найти цитируемый пост)
неправильно это. Плохо делать выделение памяти внутри функции. Так ты делаешь вызывающий код зависимым от реализации этой функции.  
Да, это так, но я хочу пока рассмотреть простую ситуацию, где нет переопределения функции new... 
Цитата(Walker @  6.6.2008,  10:45 Найти цитируемый пост)
Библиотечные функции и strcpy в том числе используют именно преопределённые буферы, за выделение и освобождение которых отвечаете Вы.
Цитата(Fazil6 @  6.6.2008,  10:56 Найти цитируемый пост)
вот те раз... приехали... нигде он ее не выделяет. Оба буфера выделены до вызова.  
Да, здесь я возможно просто неправильные примеры привел, сейчас так сходу не рожу что-нить покорректнее, но суть основного вопроса от этого меняется не сильно... Как работать с памятью при такой ситуации, как я описал?

Цитата(Mayk @  6.6.2008,  10:56 Найти цитируемый пост)
realloc курить сюда.
Ага, это если память выделена malloc... А если через new? Делать delete и new заново? Насколько это корректно с точки зрения областей видимости? А если неизвестно - через что выделена память?  smile 
Цитата
    А можно ли вообще возвращать адрес локальной переменной?
Компилятор по-этому поводу предупреждает!
Я написал, что это гипотетический пример и что он явно не рабочий... И вопрос-то как раз в том и стоит - "как мне вернуть динамически сформированную строку"?



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
MAKCim
Дата 6.6.2008, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата(Andrey44 @  6.6.2008,  11:26 Найти цитируемый пост)
А можно ли вообще возвращать адрес локальной переменной?

можно, но не нужно

Добавлено через 2 минуты и 47 секунд
Цитата(ama_kid @  6.6.2008,  11:29 Найти цитируемый пост)
Оно, конечно, может и лучше, но... фиг знает, иногда бывает необходимо и на чистом С писать, а тогда иметь на вооружении знания о работе с char* оказывается полезным...

два варианта
1. отделить функционал от работы с памятью (выделение/освобождение)
2. использовать статический буфер (TLS-буфер в случае многопоточности)




--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Alek86
Дата 6.6.2008, 11:35 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



на плюсах это легко:
Код
std::auto_ptr<char> GetString(void)
{
  char *s;
  s = new char[1000];
  return std::auto_ptr<char>(s);
}


а не ООП тем и хуже, что ты сам обязан за всем следить


--------------------
user posted image    user posted image
PM MAIL   Вверх
ama_kid
Дата 6.6.2008, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Alek86 @  6.6.2008,  11:35 Найти цитируемый пост)
а не ООП тем и хуже, что ты сам обязан за всем следить 
Да я-то и не против следить, мне собственно и нужно знать - КАК следить? Как правильно будет написать возврат строки из функции?
Цитата(MAKCim @  6.6.2008,  11:30 Найти цитируемый пост)
1. отделить функционал от работы с памятью (выделение/освобождение)
 smile для моего случая хотя бы на псевдоалгоритме 


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Mayk
Дата 6.6.2008, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(ama_kid @  6.6.2008,  15:29 Найти цитируемый пост)
А если неизвестно - через что выделена память? 

См аллокаторы в stl. 


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mes
Дата 6.6.2008, 11:53 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



и в С и в С++ работа по выделению памяти внутри функции не этична
но в С++ можно написать оболочку над буффером (чем с данной точки зрения и является std::string)
"стык" между  С и С++ приводится к сишнему виду, со всеми вытекающими проблемами..
поэтому имхо  вопрос должен относится к чистому С, а не к плюсам


Цитата(Alek86 @  6.6.2008,  11:35 Найти цитируемый пост)
Код

std::auto_ptr<char> GetString(void)
{
  char *s;
  s = new char[1000];
  return std::auto_ptr<char>(s);
}


перекосило от конструкции, хотя отработает она без проблем.
 


--------------------
PM MAIL WWW   Вверх
Alek86
Дата 6.6.2008, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(MAKCim @  6.6.2008,  11:30 Найти цитируемый пост)
отделить функционал от работы с памятью (выделение/освобождение)

думаю имелось в виду сделать 2 функции - получение длины данных и заполнение буфера
тогда

- получил длину
- создал буфер
- заполнил (GetString)
- воспользовался данными
- удалил буфер

а если получение длины неотделимо от GetString, то или выделяй большой буфер и пускай функция выдает ошибку, если его оказалось недостаточно или уж выделяй внутри функции и возвращай
Код
struct String {char* p_str; unsigned length;};


Добавлено @ 11:59
Цитата(mes @  6.6.2008,  11:53 Найти цитируемый пост)
перекосило от конструкции, хотя отработает она без проблем. 

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


Цитата(mes @  6.6.2008,  11:53 Найти цитируемый пост)
поэтому имхо  вопрос должен относится к чистому С, а не к плюсам

если функция внутри dll находится, то плюсы тут наравне с сями, ибо реализация auto_ptr не специализирована и даже размеры классов для борланда и мелкософтового компилеров могут отличаться

Это сообщение отредактировал(а) Alek86 - 6.6.2008, 12:00


--------------------
user posted image    user posted image
PM MAIL   Вверх
ama_kid
Дата 6.6.2008, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Mayk @  6.6.2008,  11:45 Найти цитируемый пост)
См аллокаторы в stl
Опять же - поднимаемся до уровня библиотеки шаблонов С++. Оно, конечно, введено в стандарт и все такое, но проблема в том, что во многих компиляторах С, применяемых, допустим, в промышленных контроллерах, она попросту отсутствует. Поэтому интересно узнать решение средствами языка, а не каких-то библиотек (даже если это и трудоёмко). Или наоборот - получить подтверждение, что это невозможно...  smile

Добавлено через 2 минуты и 32 секунды
Цитата(Alek86 @  6.6.2008,  11:55 Найти цитируемый пост)
а если получение длины неотделимо от GetString, то или выделяй большой буфер и пускай функция выдает ошибку, если его оказалось недостаточно или уж выделяй внутри функции и возвращай
Код
struct String {char* p_str; unsigned length;};
Во-во, про второй способ поподробнее пожалуйста... На что должен указывать char* p_str?


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Alek86
Дата 6.6.2008, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(ama_kid @  6.6.2008,  11:59 Найти цитируемый пост)
На что должен указывать char* p_str?

на начало строки...


--------------------
user posted image    user posted image
PM MAIL   Вверх
Mayk
Дата 6.6.2008, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(mes @  6.6.2008,  15:53 Найти цитируемый пост)
перекосило от конструкции, хотя отработает она без проблем.

delete [] != delete.

Цитата(ama_kid @  6.6.2008,  15:59 Найти цитируемый пост)
Опять же - поднимаемся до уровня библиотеки шаблонов С++. Оно, конечно, введено в стандарт и все такое, но проблема в том, что во многих компиляторах С, применяемых, допустим, в промышленных контроллерах, она попросту отсутствует. Поэтому интересно узнать решение средствами языка, а не каких-то библиотек (даже если это и трудоёмко). Или наоборот - получить подтверждение, что это невозможно..

Ну так вместо шаблонов передавай указатели на malloc/realloc/free  если так заботишся о обобщенности, делов то.


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
ama_kid
Дата 6.6.2008, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Alek86 @  6.6.2008,  12:03 Найти цитируемый пост)
на начало строки... 
А память под строку выделена\освобождена где?



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Mayk
Дата 6.6.2008, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(ama_kid @  6.6.2008,  16:07 Найти цитируемый пост)
А память под строку выделена\освобождена где?

ДО вызова/а если требутеся - то ВО время. 

Это сообщение отредактировал(а) Mayk - 6.6.2008, 12:09


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Lazin
Дата 6.6.2008, 12:11 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



можно передавать в функцию не только массив и его размер, но и указатель на функцию изменяющую размер массива...
Код

//тип функции для перераспределения памяти
typedef void* (*realloc_t)(void*, size_t);

char* get_string(char* buf/*out*/, size_t len, realloc_t realloc_)
{
   if (строка buf достаточной длинны)
   {
      записать строку в  buf, 
      return buf;
   }
   в buf слишком мало памяти
   buf = reallock_(buf, новый размер буфера);
   записать строку в buf
   return buf;
}


использовать можно как с динамическим массивом
Код

{
  char* buffer = (char*)realloc(0, 1024);
  buffer = get_string(buffer, 1024, &realloc);
}


так и с массивом размещенным в стеке
Код

void* dummy(void*, size_t)//функция - заглушка
{
 throw std::runtime_error("can't resize array in the stack");
}

{
 char buffer[1024];
 char *p = get_string(buffer, 1024, &dummy);
}

PM MAIL Skype GTalk   Вверх
Alek86
Дата 6.6.2008, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(Mayk @  6.6.2008,  12:05 Найти цитируемый пост)
delete [] != delete.

точно
интересно, какой хороший человек решил их разделять...

Цитата(ama_kid @  6.6.2008,  12:07 Найти цитируемый пост)
А память под строку выделена\освобождена где?

внутри функции
но это только в том случае, если никак не можешь отделить подсчет необходимой длины от GetString (или он просто будет долго работать)


--------------------
user posted image    user posted image
PM MAIL   Вверх
ama_kid
Дата 6.6.2008, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Mayk @  6.6.2008,  12:05 Найти цитируемый пост)
Ну так вместо шаблонов передавай указатели на malloc/realloc/free  если так заботишся о обобщенности, делов то.
Хорошо, а на что передавать указатели в случае new\delete? Аналогом realloc, кстати, в этом случае что у нас является?



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Mayk
Дата 6.6.2008, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(ama_kid @  6.6.2008,  16:12 Найти цитируемый пост)
Аналогом realloc, кстати, в этом случае что у нас является?

std::copy блин
Цитата(ama_kid @  6.6.2008,  16:12 Найти цитируемый пост)
Хорошо, а на что передавать указатели в случае new\delete?

Цитата(Mayk @  6.6.2008,  15:45 Найти цитируемый пост)
См аллокаторы в stl.  

Цитата(Mayk @  6.6.2008,  15:45 Найти цитируемый пост)
См аллокаторы в stl.  

Цитата(Mayk @  6.6.2008,  15:45 Найти цитируемый пост)
См аллокаторы в stl.  


На что передаются указатели  в аллокаторы?
На что передаются указатели  в аллокаторы?
На что передаются указатели  в аллокаторы?
На что передаются указатели  в аллокаторы?
На что передаются указатели  в аллокаторы?
На что передаются указатели  в аллокаторы?
На что передаются указатели  в аллокаторы?


Это сообщение отредактировал(а) Mayk - 6.6.2008, 12:14


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
ama_kid
Дата 6.6.2008, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Lazin, привел хороший пример, но к тебе тот же вопрос...


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Lazin
Дата 6.6.2008, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(ama_kid @  6.6.2008,  12:12 Найти цитируемый пост)
Аналогом realloc, кстати, в этом случае что у нас является?

новый массив = new[] 
memcpy из старого в новый (если нужно)
delete[] старый массив
PM MAIL Skype GTalk   Вверх
mes
Дата 6.6.2008, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alek86 @  6.6.2008,  11:55 Найти цитируемый пост)
если функция внутри dll находится

тут два варианта , или "чистый" виртуальный интерфейс, либо С -подход (не смотря на то что прога на С++)



--------------------
PM MAIL WWW   Вверх
Lazin
Дата 6.6.2008, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



в си алокаторов и new/delete нету, так к слову...
PM MAIL Skype GTalk   Вверх
nirburg
Дата 6.6.2008, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 20.3.2008

Репутация: 1
Всего: 1



ama_kid, перед вызовом подобных функций использую предварительное выделение заведомо достаточного объема памяти в стеке, либо хипе (зависит от необходимых размеров). соответственно, память освобождается в той же функции, которая ее выделяла. если максимальный размер возвращаемых данных никак заранее нельзя определить (хотя бы примерно), то, дабы не обременять себя "ментальным геморроем", использую std::string. 

т.к., судя по всему, эти пути решения вас не устраивают, можно делать "пробный" вызов функции для определения необходимого объема памяти, выделять эту память, после чего вызывать функцию "по-настоящему". такой вариант, кажется, применяется в некоторых функциях ядра Windows, или, по крайней мере, где-то недалеко от ядра smile.

поясню:
Код

char *myfunc(char *buffer, int *len)
{
    if (!*len) {
        // определение необходимого размера
        *len = ...;
    } else {
        // работа с буфером
    }
}

void otherfunc()
{
    int buflen = 0;
    char *mybuf;
    
    myfunc(NULL, &buflen);      // buflen = необходимый размер буфера, первый параметр не нужен
    mybuf = new char [buflen];  // или malloc
    myfunc(mybuf, &buflen);
    delete [] mybuf;            // или free
}


как-то так, в общем.

PM MAIL   Вверх
ama_kid
Дата 6.6.2008, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Mayk @  6.6.2008,  12:14 Найти цитируемый пост)
std::copy блин
хмм.. ну тада уж проще использовать с
std::string smile

Добавлено @ 12:20
Цитата(Lazin @  6.6.2008,  12:15 Найти цитируемый пост)
новый массив = new[] 
memcpy из старого в новый (если нужно)
delete[] старый массив 
Повторюсь - что в этом случае с областью видимости в случае использования внутри функции? Ничего, что мы выделяем память, которая будет невалидна потом?
Цитата(Lazin @  6.6.2008,  12:16 Найти цитируемый пост)
в си алокаторов и new/delete нету, так к слову... 
Ну, на самом деле иногда приходится работать со срещенным С\С++ - new\delete есть, а библиотеки шаблонов нет smile
Добавлено @ 12:21
Цитата(nirburg @  6.6.2008,  12:17 Найти цитируемый пост)
как-то так, в общем
В общем-то полностью согласен, и изначальный вопрос родился из мыслей: "а нельзя ли сделать как-нить эдак, чтобы не так?!"


Это сообщение отредактировал(а) ama_kid - 6.6.2008, 12:27


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Alek86
Дата 6.6.2008, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(mes @  6.6.2008,  12:16 Найти цитируемый пост)
или "чистый" виртуальный интерфейс

даже чистый вирт интерфейс не может работать с переменными типов std::auto_ptr и т.п.


--------------------
user posted image    user posted image
PM MAIL   Вверх
mes
Дата 6.6.2008, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alek86 @  6.6.2008,  12:24 Найти цитируемый пост)
даже чистый вирт интерфейс не может работать с переменными типов std::auto_ptr и т.п. 

естественно ..  однако это не мешает использовать нам их в реализации ..




--------------------
PM MAIL WWW   Вверх
Lazin
Дата 6.6.2008, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(ama_kid @  6.6.2008,  12:17 Найти цитируемый пост)
Повторюсь - что в этом случае с областью видимости в случае использования внутри функции? Ничего, что мы выделяем память, которая будет невалидна потом?

все будет ОК, что-бы удалить блок памяти, не нужно знать его размер
PM MAIL Skype GTalk   Вверх
nirburg
Дата 6.6.2008, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 20.3.2008

Репутация: 1
Всего: 1



Цитата(ama_kid @  6.6.2008,  12:17 Найти цитируемый пост)
"а нельзя ли сделать как-нить эдак, чтобы не так?!"

как-нибудь эдак, конечно, можно. вопрос - нужно ли? smile 

(шепотом) там народ уже интерфейсы обсуждает )) скоро, чувствую, все сведется к необходимости создания дерева классов со сложной иерархией, наследованием, и прочей модной шелухой =)
PM MAIL   Вверх
mes
Дата 6.6.2008, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



тем более вопрос был не об auto_ptr , а о том как избежать проблем с выделением памяти внутри функции

Добавлено через 1 минуту и 11 секунд
Цитата(nirburg @  6.6.2008,  12:32 Найти цитируемый пост)
(шепотом) там народ уже интерфейсы обсуждает )) скоро, чувствую, все сведется к необходимости создания дерева классов со сложной иерархией, наследованием, и прочей модной шелухой =) 

))



--------------------
PM MAIL WWW   Вверх
ama_kid
Дата 6.6.2008, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(Lazin @  6.6.2008,  12:31 Найти цитируемый пост)
все будет ОК, что-бы удалить блок памяти, не нужно знать его размер 
Удалить-то мы его удалим, а куда денется выделенная по-новой память при выходе из функции?



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
mes
Дата 6.6.2008, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(ama_kid @  6.6.2008,  12:35 Найти цитируемый пост)
Удалить-то мы его удалим, а куда денется выделенная по-новой память при выходе из функции?

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


--------------------
PM MAIL WWW   Вверх
ama_kid
Дата 6.6.2008, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(mes @  6.6.2008,  12:39 Найти цитируемый пост)
в остальных как и говорилось выше - нужно выделять памятж вне функции
Опять же - а если вне функции неизвестен размер требуемой памяти?

Хорошо, у меня вроде бы сформировался более-менее основной вопрос, попробую его сформулировать: как после выполнения оператора
Код

char * s = new char[2] = "";
... 
 s = GetString();
...
delete s;
получить корректный буфер s (т.е. что должно быть вместо "..." и внутри функции GetString? ), при условиях: 
1) размер строки становится известен только внутри GetString()... 
2) пользуясь new\delete? 
P.S. Для случаев с malloc\realloc\free я более-менее уже понимаю... 



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
vinter
Дата 6.6.2008, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



присваивать так низя, юзай strcpy


--------------------
Мой блог
PM MAIL WWW   Вверх
ama_kid
Дата 6.6.2008, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(vinter @  6.6.2008,  13:01 Найти цитируемый пост)
присваивать так низя, юзай strcpy 
что передавать в strcpy? 
Ну это гипотетический пример, хоть strcpy, хоть что-то другое , без разницы, главное - на выходе получить валидный буфер


Это сообщение отредактировал(а) ama_kid - 6.6.2008, 13:08


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Fazil6
Дата 6.6.2008, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(ama_kid @  6.6.2008,  12:51 Найти цитируемый пост)
получить корректный буфер s (т.е. что должно быть вместо "..." и внутри функции GetString? ), при условиях: 
1) размер строки становится известен только внутри GetString()... 
2) пользуясь new\delete? 

Код

unsigned int GetString( char* buf , unsigned int buf_len)
{
     // пишем сколько влазит
     // возвращаем сколько нужно чтобы влезло
}

// если вернуло больше чем buf_len, то значит вернули не все


Добавлено через 1 минуту и 8 секунд
кстати 
Код

delete [] s;

PM MAIL   Вверх
ama_kid
Дата 6.6.2008, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Fazil6, ага, вариант понятен... В принципе, я так и делал всегда...

Кстати, щас только сообразил, что непроходимо туплю - сам же на свой вопрос вывесил в топике ответ - ссылка ответа от RAN. В связи с этим вопрос - насколько корректен приведённый там пример? Просто никто там после этого не отписался по поводу правильности\неправильности. Если он правилен - тогда вопрос снимается...



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
JackYF
Дата 6.6.2008, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Ого, сколько написали...

Подытожу по себе (то есть, как бы это делал я).
Варианта 2:

1) целевой язык - С

Код

char* func(int param)
{
  unsigned int size;
  //...
  char* p = new char[size];
  return p;
}

//...
char* u = func(n);
//...
delete [] u;


2) целевой язык - С++
Код

std::string func(int param)
{
  std::string buf;
  //...
  return buf;
}

//...

std::string u = func(n);
//...


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

Это сообщение отредактировал(а) JackYF - 6.6.2008, 13:26


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
ama_kid
Дата 6.6.2008, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



Цитата(JackYF @  6.6.2008,  13:25 Найти цитируемый пост)
В первом случае ты сам заботишься о том, чтобы освободить выделенную внутри функции память
ага, а не будет ли в этом случае Access Violation в связи с доступом к невалидному участку памяти? Или участок памяти, выделенный внутри функции будет валидным?



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
nirburg
Дата 6.6.2008, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 20.3.2008

Репутация: 1
Всего: 1



JackYF, в C нет new и delete  smile 
PM MAIL   Вверх
mes
Дата 6.6.2008, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(JackYF @  6.6.2008,  13:25 Найти цитируемый пост)
1) целевой язык - С

Цитата(JackYF @  6.6.2008,  13:25 Найти цитируемый пост)
char* p = new char[size];

 smile  smile 

Цитата(ama_kid @  6.6.2008,  13:19 Найти цитируемый пост)
сам же на свой вопрос вывесил в топике ответ - ссылка ответа от RAN

как я понял имеется ввиду этот ответ:
http://forum.vingrad.ru/index.php?showtopi...st&p=109698

Код

void change_string(char* param) // передаем указатель на память 
{
   delete param; // удаляем .. не этично, хотя сработает если внимательно следить  
   const char str[] = "new string";
   param = NULL;
   param = new char[ sizeof(str) ]; // выделили память - но она станет не валидной после завершения функции 

// как минимум надо было  написать void change_string(char*&param) -
// но даже в ьтом случае пример выглядит не очень приятно ))





Это сообщение отредактировал(а) mes - 6.6.2008, 13:33


--------------------
PM MAIL WWW   Вверх
Fazil6
Дата 6.6.2008, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(ama_kid @  6.6.2008,  13:19 Найти цитируемый пост)
ссылка ответа от RAN. В связи с этим вопрос - насколько корректен приведённый там пример?


Зная этого чела лично, могу сказать с определенностью, что сейчас он так делать не стал бы.  smile 
Я тоже так делать не сталбы.
Код

void getTq(char * p)
{
    delete p;   //  ЧПОК!!!!!!!!
}


int main()
{
    char s[] = "!!!";
    getTq(s);
    return 0;
}

PM MAIL   Вверх
nirburg
Дата 6.6.2008, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 20.3.2008

Репутация: 1
Всего: 1



Цитата(mes @  6.6.2008,  13:32 Найти цитируемый пост)
param = new char[ sizeof(str) ]; // выделили память - но она станет не валидной после завершения функции 

ну вот, приехали. new, оказывается, выделяет память в стеке? или C++ обзавелся хитрым сборщиком мусора, который подтирает всю выделенную в функции память?
PM MAIL   Вверх
mes
Дата 6.6.2008, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(nirburg @  6.6.2008,  13:41 Найти цитируемый пост)
Цитата(mes @  6.6.2008,  13:32 )
param = new char[ sizeof(str) ]; // выделили память - но она станет не валидной после завершения функции 
ну вот, приехали. new, оказывается, выделяет память в стеке? или C++ обзавелся хитрым сборщиком мусора, который подтирает всю выделенную в функции память? 

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

в коментариях в предыдушем посту это и указано  ))

Это сообщение отредактировал(а) mes - 6.6.2008, 13:48


--------------------
PM MAIL WWW   Вверх
Daevaorn
Дата 6.6.2008, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(mes @  6.6.2008,  14:47 Найти цитируемый пост)
просто значения указателя не возврашается из функции - т.е указатель переданный в функцию, после ее завершения, продолжает показывать  на ту же самую область что и раньше

Не, ну выделить память внутри функции и выдать её наружу вполне себе юзкейс. Так, допустим, malloc поступаетsmile
PM MAIL WWW   Вверх
mes
Дата 6.6.2008, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Daevaorn @  6.6.2008,  13:59 Найти цитируемый пост)
Не, ну выделить память внутри функции и выдать её наружу вполне себе юзкейс. Так, допустим, malloc поступает 

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



--------------------
PM MAIL WWW   Вверх
nirburg
Дата 6.6.2008, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 20.3.2008

Репутация: 1
Всего: 1



mes, прошу прощения, неправильно понял smile да, вы правы, param будет указывать в космос

Daevaorn, ну malloc'y на роду написано память внутри себя выделять. а если так будет поступать каждая гордая функция, то что с программой будет твориться, я не представляю
PM MAIL   Вверх
mes
Дата 6.6.2008, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



malloc и new тем и хороши что всегда не задумываясь (о том как реализована функция) понятно, что делает функция и одназначно напрашивается вывод о применение ее антонима.
однако, что нужно делать после функции GetString (..) (удалять память или нет)  имхо отнюдь не очевидно  smile 
поэтому (на мой взгляд)  и принято "неписанное " соглашении о использовании внутри функции зараннее выделенного буффера..

Это сообщение отредактировал(а) mes - 6.6.2008, 14:12


--------------------
PM MAIL WWW   Вверх
Daevaorn
Дата 6.6.2008, 14:15 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(mes @  6.6.2008,  15:07 Найти цитируемый пост)
поьтому и принято (на мой взгляд) "неписанное " соглашении о использовании внутри функции зараннее выделенного буффера

а если строка больше чем буфер? Тогда ещё одну функцию заводить, которая вернет размер, потом выделить память, и только потом передать в функцию - много буквsmile

Хотя, конечно, это оптимально с точки зрения прозрачности кода.
PM MAIL WWW   Вверх
JackYF
Дата 6.6.2008, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(nirburg @  6.6.2008,  12:28 Найти цитируемый пост)
JackYF, в C нет new и delete 

 smile Верно smile
Код

char* func(int param)
{
  unsigned int size;
  //...
  char* p = (char*) malloc(size);
  return p;
}
//...
char* u = func(n);
//...
free(u);




--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
mes
Дата 6.6.2008, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Daevaorn @  6.6.2008,  14:15 Найти цитируемый пост)
а если строка больше чем буфер? Тогда ещё одну функцию заводить, которая вернет размер, потом выделить память, и только потом передать в функцию - много букв  

вот пример без добавления второй функции 
Код


int GetString (char *p, int size) // возврашает кол-во символов непоместившихся в буффер
{ ..
};

void Test()
{
   int size =   GetString( NULL, 0);

   char *p = new char(size); 
   GetString(p, size);
   ...
   delete...

};



--------------------
PM MAIL WWW   Вверх
Daevaorn
Дата 6.6.2008, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(mes @  6.6.2008,  16:01 Найти цитируемый пост)
вот пример без добавления второй функции 

ну по сути вы её добавили, сделав в GetString проверку `if( p == 0 )`.
PM MAIL WWW   Вверх
ama_kid
Дата 6.6.2008, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 2
Всего: 95



В общем, как я понял, сделать средствами new\delete (без привлечения библиотек-контейнеров и выкрутасов с несколькими функциями\вызовами) аналогичный дельфёвому фокус не удастся. Что ж, будет еще один плюс в пользу malloc\realloc smile  Думаю, тему можно закрывать, потому что обсуждение идет по десятому кругу, всем спасибо за активное обсуждение...  smile
Хотя, если появятся новые идеи - буду рад увидеть, да и для потомков, думаю, будет полезно...  smile 


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2284 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.