C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Оператор delete, Корректное удаление указателя
__Cheat3r
Отправлено: 10.10.2006, 14:47


Станционный диспетчер

Группа: Участник
Сообщений: 110



есть функция:
CODE


TSomeClass *GetData(...)
{
  TSomeClass * sc= new TSomeClass();
  ...
  ...
  return sc;
}



и вторая функция:
CODE

void CheckIt(TSomeClass * sc)
{
  ...
  ...
}


Вызываю как
CODE

CheckIt(GetData(...));


Как мне очистить память после TSomeClass * sc= new TSomeClass(); ? После return вызывать оператор толку нет. Вызывать до, — ошибка, естественно.

Спасибо.
gvg
Отправлено: 10.10.2006, 15:37


Машинист паровоза

Группа: Участник
Сообщений: 222



Наверное, создать класс в GetData, использовать его сколько надо, как не нужен — удалить.


CODE

TSomeClass *someclass = GetData(...);
CheckIt( someclass );
...
...
delete someclass;
olegenty
Отправлено: 10.10.2006, 15:51


Ветеран

Группа: Модератор
Сообщений: 2412



можно обернуть в auto_ptr, тогда после последнего использования (после выхода из области видимости последнего блока, где использовался) экземпляр класса будет удалён автоматически
Gal
Отправлено: 10.10.2006, 18:07


Станционный диспетчер

Группа: Участник
Сообщений: 124



А так не пробовили?
CODE

 TSomeClass * sc= new TSomeClass();
_try
{
 ...
 ...
 return sc;
}
_finally
{
  delete sc;
}
__Cheat3r
Отправлено: 11.10.2006, 09:30


Станционный диспетчер

Группа: Участник
Сообщений: 110



gvg, там скорее всего будет ошибка. Invalisd pointer operation.

olegenty, можно небольшой примерчик?


Gal, хехе. до вашего finally дело не дойдёт.
__Cheat3r
Отправлено: 11.10.2006, 09:32


Станционный диспетчер

Группа: Участник
Сообщений: 110



я так понял, что делать нужно так:


CODE

auto_ptr<TSomeClass> ptr(new TSomeClass());



не понятно, что делать дальше с ptr.
olegenty
Отправлено: 11.10.2006, 09:49


Ветеран

Группа: Модератор
Сообщений: 2412



всё, что хочешь. можешь его вернуть. главное не забывать, что auto_ptr — указатель с ПЕРЕДАЧЕЙ ВЛАДЕНИЯ.

это значит:

CODE

auto_ptr<TStringList> ptr(new TStringList()); // ptr указывает на TStringList
auto_ptr<TStringList> ptr1 = ptr; // ptr1 указывает на TStringList, а ptr указывает на фуфло
gvg
Отправлено: 11.10.2006, 11:35


Машинист паровоза

Группа: Участник
Сообщений: 222



QUOTE (__Cheat3r @ 11.10.2006, 10:30)
gvg, там скорее всего будет ошибка. Invalisd pointer operation.

Это с чего же? Я исходил из того, что delete в GetData отсутствует...
Shagg
Отправлено: 11.10.2006, 14:10


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Слуште а вам не кажется кощунством возврашать из функции указатель, который указывает на память выделяемую в самой функции
ведь не всегда происходит вызов
CODE
CheckIt(GetData(...));

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

попробуйте возвращать не указатель, а сам объект, который точно будет разрушен при выходе из блока
olegenty
Отправлено: 11.10.2006, 14:22


Ветеран

Группа: Модератор
Сообщений: 2412



2 Shagg — NO PROBLEM, если этот указатель "обёрнут" в auto_ptr. делаю так без зазрения совести. про проблемы с очисткой памяти ОЧЕНЬ ДАВНО забыл. потому что оператором delete не пользуюсь. зачем он, если есть auto_ptr...
gvg
Отправлено: 11.10.2006, 16:02


Машинист паровоза

Группа: Участник
Сообщений: 222



QUOTE (Shagg @ 11.10.2006, 15:10)
Слуште а вам не кажется кощунством возврашать из функции указатель, который указывает на память выделяемую в самой функции

2Shagg
Что значит
QUOTE
ведь функция GetData(...) может вызываться и сама по себе
По своему желанию? biggrin.gif
И почему бы функции не возвращать указатель на память, выделенную в этой функции? Главное — не потерять значение этого указателя, чтобы потом освободить эту память.
exp
Отправлено: 12.10.2006, 16:25


Мастер участка

Группа: Участник
Сообщений: 304



Объясните, почему нельзя сделать так?
CODE

TSomeClass *ptr=GetData();
CheckIt(ptr);
delete ptr;
Shagg
Отправлено: 12.10.2006, 16:40


Дежурный стрелочник

Группа: Участник
Сообщений: 69



2gvg:
я имел в виду то, что функцию можно вызвать и не присваивая какойнить переменной значения, возвращаемого ею. В таком случае память действительно будет потеряна. А надеяться на то, что "я всегда буду использовать указатель, возвращаемый функцией и освобождать память" довольно глупо. Особенно если этой функцией будут пользоваться несколько человек. У них руки так и будут чесаться вызвать функцию не получив ее результата.

2olegenty: поддерживаю идею использования классов-оберток. Про auto_ptr не знал, приходилось подобные "обертки" писать самому. Спасибо за идею.
__Cheat3r
Отправлено: 12.10.2006, 18:10


Станционный диспетчер

Группа: Участник
Сообщений: 110



gvg, извиняюсь.. голова уже просто забита этими указателями, delet'ами, и т.д. Вариант, конечно, сработает, но это ведь неудобно...
Gal
Отправлено: 13.10.2006, 12:53


Станционный диспетчер

Группа: Участник
Сообщений: 124



QUOTE

Gal, хехе. до вашего finally дело не дойдёт.

__Cheat3r — не делайте скорополительных выводов, поставте точку останова и убедитесь.
finally — отработает!
__Cheat3r
Отправлено: 13.10.2006, 13:49


Станционный диспетчер

Группа: Участник
Сообщений: 110



Вобщем, насколько я понял с auto_ptr работаем так:
CODE

TScvUsersFontInfo * FontOf(int UserID)
{
auto_ptr<TScvUsersFontInfo> out(new TScvUsersFontInfo());
out->...
out->...

return out.release();


}

2olegenty: Так это делается?

__Cheat3r
Отправлено: 13.10.2006, 13:57


Станционный диспетчер

Группа: Участник
Сообщений: 110



Gal, действительно.

Век живи — век учись.
__Cheat3r
Отправлено: 13.10.2006, 15:12


Станционный диспетчер

Группа: Участник
Сообщений: 110



Хм. или я д­­урак, или CodeGuard?
CODE

The object (0x01108F60) [size: 4 bytes] was created with new
Error 00878. 0x300010 (Thread 0x0D18):
Resource leak: The object (0x4198210) was never deleted

The object (0x04198210) [size: 12 bytes] was created with new
| D:\SmartyProject\Base\includes/Windows.cpp line 28:
| TScvUserFontInfo *TScvWnds::FontOf(String Key)
| {
|> auto_ptr<TScvUserFontInfo>FontInfo(new TScvUserFontInfo());
|
|
Call Tree:
0x00405BB5(=Base.exe:0x01:004BB5) D:\SmartyProject\Base\includes/Windows.cpp#28
0x0040C3A2(=Base.exe:0x01:00B3A2) D:\SmartyProject\Base\includes/Windows.cpp#671
0x00408B83(=Base.exe:0x01:007B83) D:\SmartyProject\Base\includes/Windows.cpp#289
0x0045CD88(=Base.exe:0x01:05BD88) D:\SmartyProject\Base\FormMain.cpp#2101
0x00460316(=Base.exe:0x01:05F316) D:\SmartyProject\Base\FormMain.h#541
0x005006B4(=Base.exe:0x01:0FF6B4) Controls.pas#5143


Отредактировано __Cheat3r — 14.10.2006, 02:12
olegenty
Отправлено: 13.10.2006, 15:21


Ветеран

Группа: Модератор
Сообщений: 2412



2 __Cheat3r
нет, нет так.
вот так:
CODE

typedef auto_ptr<ScvUsersFontInfo> ScvUsersFontInfoPtr;
ScvUsersFontInfoPtr FontOf(int UserID)
{
   ScvUsersFontInfoPtr out(new TScvUsersFontInfo());
   ...
   out->...
   out->...
   ...
   return out;
}

Вернуться в Вопросы программирования в C++Builder