ссылка на динамическую переменную
От: Аноним  
Дата: 14.10.04 11:51
Оценка:
Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?
Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?
Re: ссылка на динамическую переменную
От: Аноним  
Дата: 14.10.04 11:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?

Ничего плохого, если там, куда вернешь ссылку или еще где-то (где тебе нужно) не забудешь освободить память.
Re: ссылка на динамическую переменную
От: Glоbus Украина  
Дата: 14.10.04 11:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?


using namespace std;

class A{

};


int main(){
    A* ptr = new A;
    A& ref = *ptr;
    delete &ref;
}
Удачи тебе, браток!
Re: ссылка на динамическую переменную
От: Bell Россия  
Дата: 14.10.04 11:56
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

Все зависит от контекста.

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?

В этом случае вся ответственность на тебе (ну или на пользователе этой функции).
Чтобы освободиться от этой ответственности, обычно используются умные указатели.
Любите книгу — источник знаний (с) М.Горький
Re: ссылка на динамическую переменную
От: Кодт Россия  
Дата: 14.10.04 12:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?

Ты имеешь в виду
int& foo() { int*p=new int(123); return *p; }
int& bar() { static int v=123; return v; }

int main()
{
  int& f = foo();
  int& b = bar();
  f += b; b -= f; f += b;
  delete &f;
}

С точки зрения компилятора — ничего криминального нет. Но делать так — однозначно не стоит!
Во-первых, заподло для сопровождения программы. Почему память из-под ссылки f нужно удалять, а из-под b — нельзя?
Во-вторых, проблема с перегруженным оператором &
struct figvam
{
  char c[1000];
  int x;

  int* operator& () { return &x; }
};

figvam& fig() { return *new figvam; }

int main()
{
  figvam& f = fig();
  delete &f; // &f имеет тип int* и указывает бог весть куда
}

В-третьих, элементарная забывчивость (см. "во-первых")
int& boo() { printf("boo!"); return *new int(); }

int main()
{
  boo(); boo(); boo();
}

Итого: хочешь возвращать динамические данные — возвращай указатель. Желательно — умный, с подходящей политикой владения.
Перекуём баги на фичи!
Re[2]: ссылка на динамическую переменную
От: mihauzen Украина  
Дата: 14.10.04 13:49
Оценка:
Здравствуйте, Кодт, Вы писали:

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

...
class A
{
  void f(BYTE** ppData){ *ppData = (BYTE*)malloc(need_size);}
};
...
main()
{
BYTE* b;
A clsA;
clsA.f(&b);
....
free(b);
}

В таком виде, как в примере — работает замечательно. Но, если класс А "засунуть" в DLL при попытке освобождения памяти free(b) вылетает ошибка. Т.к. я не знаток работы с DLL, то не знаю почему и из-за чего это происходит. Если же добавить в класс А в DLL свою функцию:

void А::Free(BYTE* pData){free(pData);}

и вызывать ее:

main(){ ... clsA.Free(b); ...}

То ошибки не появляется.

Почему появляется ошибка про которую я говорил раньше?
...все это временно... (с) Айэм
Re: ссылка на динамическую переменную
От: jazzer Россия Skype: enerjazzer
Дата: 14.10.04 15:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?


Лучше вернуть указатель.
Потому что когда видишь функцию, возвращающую указатель, сразу возникает вопрос: "Кто будет память освобождать?"
С функцией же, возвращающей ссылку, такая мысль в голову не придет (буквально вчера или сегодня в нашем проекте обнаружилась точно такая же проблема — все долго смеялись, ибо никому даже в голову не пришло освободить полученную по ссылке память).

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?


Когда приемник позовет delete.
Все очевидно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: ссылка на динамическую переменную
От: Кодт Россия  
Дата: 14.10.04 16:18
Оценка:
Здравствуйте, mihauzen, Вы писали:

M>Имею почти такую же ситуацию. Есть класс в нем функция, которая выделяет память, а освобождаю память по завершению работы этой функции в коде основной процедуры.


M>В таком виде, как в примере — работает замечательно. Но, если класс А "засунуть" в DLL при попытке освобождения памяти free(b) вылетает ошибка. Т.к. я не знаток работы с DLL, то не знаю почему и из-за чего это происходит. Если же добавить в класс А в DLL свою функцию:

M>void А::Free(BYTE* pData){free(pData);}

M>и вызывать ее:
M>То ошибки не появляется.
M>Почему появляется ошибка про которую я говорил раньше?

Ага! Так сразу бы и сказал

История в том, что функции malloc/free — это интерфейс некоей сущности "менеджер кучи", которая живёт в CRT.
Если твои DLL и/или EXE прилинковывают CRT статически, то в связке EXE+DLL оказываются два экземпляра этого менеджера.
Ты выделяешь память в одном, а убиваешь в другом, приводя его в изумление.
Когда же ты написал экспортируемую функцию A::Free (определённую в DLL), она обращается к тому же менеджеру, что и выделял память.

Как лечить?
* Использовать глобальный менеджер кучи, предоставляемый системой. Например, в COM-приложениях это TaskMemAlloc/TaskMemFree.
* Линковать CRT динамически во всех модулях (см. опции компилятора | настройки проекта)
Перекуём баги на фичи!
Re[4]: ссылка на динамическую переменную
От: Шахтер Интернет  
Дата: 14.10.04 16:57
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К>Как лечить?

К>* Использовать глобальный менеджер кучи, предоставляемый системой. Например, в COM-приложениях это TaskMemAlloc/TaskMemFree.

CoTaskMemAlloc/CoTaskMemFree

Но лучше тогда уж использлвать Default Heap. Доступ к нему можно получить вызовом GetProcessHeap.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: ссылка на динамическую переменную
От: Шахтер Интернет  
Дата: 14.10.04 16:57
Оценка: +2
Здравствуйте, <Аноним>, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?

В подобных случаях можно рассмотреть альтернативу -- переменную создавать в вызывающей процедуре и передавать ссылку на неё вызываемой, что бы та заполнила переменную требуемым значением.
В этом случае нередко можно обойтись без динамической памяти и появляется дополнительная гибкость -- метод размещения переменной не прошит жестко в функции, а может быть выбран вызывающей процедурой.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: ссылка на динамическую переменную
От: Кодт Россия  
Дата: 14.10.04 17:18
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>CoTaskMemAlloc/CoTaskMemFree


Ну да. Под вечер голова нагрелась, память сбоит
Перекуём баги на фичи!
Re[6]: ссылка на динамическую переменную
От: Шахтер Интернет  
Дата: 14.10.04 17:56
Оценка: :))
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Шахтер, Вы писали:


Ш>>CoTaskMemAlloc/CoTaskMemFree


К>Ну да. Под вечер голова нагрелась, память сбоит


Пивка холодненького -- остудить.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: ссылка на динамическую переменную
От: Losar Россия  
Дата: 14.10.04 21:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?

1. Не плохо
2. Удалить можно после использования
Re: ссылка на динамическую переменную
От: Centaur Россия  
Дата: 15.10.04 08:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?


Плохо. Уже говорили тут, что никому не придёт в голову освободить память.

Полезнее будет сделать примерно так:

class A
{
  // ...
public:
  A(/*...*/);
};

std::auto_ptr<A> makeA(/*...*/)
{
  // ...;
  return std::auto_ptr<A>(new A(/*...*/));
}

int main(int, char**)
{
  {
    std::auto_ptr<A> a = makeA(/*...*/);
    // здесь что-то делаем с *a
  } // здесь a выходит из области видимости, деструктируется и память освобождается

  // а вот тут попробуем проигнорировать возвращаемое значение
  makeA(/*...*/); // 1. нам вернули временный объект класса std::auto_ptr<A>
                  // 2. мы его потеряли
                  // 3. он деструктировался, освобождая память
}

Читать по теме: Евангелие от Саттера (Exceptional C++), Item 37.
Re: ссылка на динамическую переменную
От: Анна Савельева  
Дата: 18.10.04 06:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Плохо ли выделить в функции память для некоторой динамической переменной, а затем вернуть ссылку на неё?

А>Когда в таком случае будет освобождена (или как можно будет освободить) память из под неё?

Вообще-то этот прием много где используется, например в strdup и других функциях стандартной библиотеки
Re[2]: ссылка на динамическую переменную
От: Аноним  
Дата: 18.10.04 07:04
Оценка:
Здравствуйте, Анна Савельева, Вы писали:

АС>Вообще-то этот прием много где используется, например в strdup и других функциях стандартной библиотеки


Испльзуется, да. Но лучше не использовать

char *_strdup( const char *strSource );


Ну тут обсуждали ссылку, то есть, (А&) а не указатель (A*). Тут западла не ждешь, однако ага! Вот оно!

И, во-вторых, даже возврат "сырого" указателя это плохо в С++.
Так как не понятно, чем его освобожадать.
delete[], delete, free, MyDeallocotor, LocalFree, CoTaskMemFree, SysFreeString.........
Юниксоиды тоже могут, наверное, неслабый список привести.

В С просто по другому нельзя, поэтому strdup — это для использования в С, в С++ ее лучше не применять.
Re[2]: ссылка на динамическую переменную
От: elcste  
Дата: 18.10.04 07:21
Оценка:
Здравствуйте, Анна Савельева, Вы писали:

АС>Вообще-то этот прием много где используется, например в strdup и других функциях стандартной библиотеки


strdup — не функция стандартной библиотеки.
Re[3]: ссылка на динамическую переменную
От: MaximE Великобритания  
Дата: 18.10.04 07:26
Оценка: +1
> И, во-вторых, даже возврат "сырого" указателя это плохо в С++.
> Так как не понятно, чем его освобожадать.

... И надо ли вообще освобождать.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.