The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Освобождение памяти в деструкторе шаблонного класса"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от muxas emailИскать по авторуВ закладки(??) on 02-Авг-05, 16:47  (MSK)
Здравствуйте,

Есть класс, реализующий динамический массив. Предполагается хранить в нем указатели на любые динамические структуры, которые создаются вызовом new()  ВНЕ этого класса. Чтобы не зависеть от типа указателя, есть смысл написать этот класс в виде шаблона. Вопрос в том, как особождать память, которую занимают созданные объекты. Очень удобно было бы автоматически зачищать ее ВНУТРИ деструктора шаблонного класса. Такое возможно? Если да, то как? Ниже мой вариант. Для проверки зачистки я использую модуль MemWatch, так он ругается на всех выделениях памяти, и говорит, что память unfreeed. Поэтому и возник этот вопрос. Очень нуждаюсь в помощи - работа стоит, т.к. может всю базу нахрен нужно переписывать.

template <class AnyType> class DynArray
{
private:
  AnyType *items;  // сам массив
  long int ntotal;  // всего выделено памяти
  long int ncurrent; // всего занято памяти
  long int nstep;  // шаг выделения
public:
  DynArray() {};
  DynArray(long int ArraySizeExpansion);
  ~DynArray();
  AnyType operator[](long int index);
  int append(AnyType item);
  void remove(long int index);
  long int length() { return ncurrent; };
enum {
  NO_ERRORS=0,
  NOT_ENOUGH_MEMORY
  };
};

template<class AnyType> DynArray<AnyType>::DynArray(long int ArraySizeExpansion)
{
  ntotal = nstep = (ArraySizeExpansion==0)?1:ArraySizeExpansion;
  ncurrent = 0;  
  items = (AnyType*) malloc(sizeof(AnyType)*nstep); << MemWatch материться на этой строке
  memset(items,0,sizeof(AnyType)*nstep);
};

template<class AnyType> DynArray<AnyType>::~DynArray()
{
  for (long int i=0;i<ncurrent;i++) delete items[i]; //<< очень удобный вариант зачистки
  free(items);
};

template<class AnyType> AnyType DynArray<AnyType>::operator[](long int index)
{
  return items[index];
};

template<class AnyType> int DynArray<AnyType>::append(AnyType item)
{
  if (ncurrent>=ntotal) {
    AnyType *newitems = (AnyType*)realloc(items,sizeof(AnyType)*(ntotal+nstep));
  if (newitems==NULL) {
    return NOT_ENOUGH_MEMORY;
  };
  items = newitems;
  memset(&items[ncurrent],0,sizeof(AnyType)*nstep);
  ntotal+=nstep;
  items[ncurrent] = item;
  ncurrent++;
  return NO_ERRORS;
};

template<class AnyType> void DynArray<AnyType>::remove(long int index)
{
  delete items[index];     //<< здесь тоже
  memset(items+ncurrent-1,0,sizeof(AnyType)*(ntotal-ncurrent+1));
  ncurrent--;
};

  Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от Maxim Kuznetsov Искать по авторуВ закладки on 02-Авг-05, 18:08  (MSK)
в чём разница приведённого фрагмента и
std::vector<AnyClass> myarr ?
лучше досочините SmartPointer ;-)

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от muxas emailИскать по авторуВ закладки(??) on 03-Авг-05, 12:47  (MSK)
Если честно, то не знаю, в чем разница, т.к. не смотрел исходников vector'a. Свой написал только потому, что не хочу пользоваться stdlib - растет размер и падает скорость.

Так по утечке памяти что-то можно сказать исходя из приведенного кода?


  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от Maxim Kuznetsov Искать по авторуВ закладки on 03-Авг-05, 13:27  (MSK)
вообще по коду - бред
срочно читайте книги на предмет понятий динамической памяти,указателей
и массивов


  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от muxas emailИскать по авторуВ закладки(??) on 03-Авг-05, 13:58  (MSK)
>вообще по коду - бред

Поконкретнее плиз :-)

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от Maxim Kuznetsov Искать по авторуВ закладки on 03-Авг-05, 14:32  (MSK)
>>вообще по коду - бред
>
>Поконкретнее плиз :-)
1) если предполагаеся хранить указатели, то тип массива: AnyType **
(в принципе далее можно и не комментировать)
2) последовательность действий (в append мелькала)
  memset(&obj,0,sizeof(obj));
  obj=another_obj;
  приводит к краху системы
3) append - это вообще шедевр!
функция добавляет элемент, но куда(позицию/индекс/ключ), она никому не скажет, потому что неположенно ;-)
  

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от muxas emailИскать по авторуВ закладки(??) on 03-Авг-05, 15:02  (MSK)

>1) если предполагаеся хранить указатели, то тип массива: AnyType **

Все немного проще :-)

typedef DynArray<SQLParam*> SQLParamArray;

>>2) последовательность действий (в append мелькала)
>>  memset(&obj,0,sizeof(obj));
>>  obj=another_obj;
>>  приводит к краху системы

Вы невнимательны. Нули проставляются только в добавленной памяти (realloc'ом), а не в уже занятой.

Указатель на объект присваивается первой пустой ячейке в массиве, т.к. ncurrent указывает не на последний занятый элемент, а на первый свободный (это не очевидно, я случайно пропустил комментарий).

>>3) append - это вообще шедевр!
>>функция добавляет элемент, но куда(позицию/индекс/ключ), она никому не >>скажет, потому что неположенно ;-)

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

Ну хоть посоветуйте какой-либо инструмент, вроде Valgrid только под FreeBSD... Я что-то не могу ничего найти, но ведь как-то FreeBSD'ишники отслуживают утечки и неправильные обращения с памятью.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

12. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от AnToXa emailИскать по авторуВ закладки(ok) on 05-Авг-05, 20:14  (MSK)
>Если честно, то не знаю, в чем разница, т.к. не смотрел исходников
>vector'a. Свой написал только потому, что не хочу пользоваться stdlib -
>растет размер и падает скорость.

это кто вам такую глупость сказал?

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от xhk Искать по авторуВ закладки on 04-Авг-05, 14:03  (MSK)
У вас тут банальная ошибочка допущена. Нельзя смешивать new/delete с malloc/free. В конструкторе выделение происходит с помощью malloc, а в remove память освобождается с помощью delete. Каша какая-то. И вообще realloc не самый лудший способ создания динамических массивов в плане производительности. Лучше выделять доп. куски памяти размером в страницу. Так куда эффективнее получитса.
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от muxas emailИскать по авторуВ закладки(??) on 04-Авг-05, 15:34  (MSK)
Может быть вы правы? Я рассуждал так:

В этой строке Malloc'ом  выделяется место под массив указателей в конструкторе (AnyType==PointerToAnyObject):
>> items = (AnyType*) malloc(sizeof(AnyType)*nstep);

Это место зачищается с помощью строки в деструкторе:
>> free(items);

Сами объекты создаются где-то вне массива с помощбю new(). А строчка
>> delete items[index];
возможно (это и есть первоначальный вопрос) будет удалять этот объект. Не массив указателей! Он удаляется в деструкторе.

Т.е. весь вопрос в том, что делает эта последняя строка - удаляет она объект или нет. Вроде по логике, выражение items[index] должно возвращать указатель на объект из массива указателей. Следовательно теоретически его (этот объект) можно грохнуть изнутри массива оператором delete. Вот только что происходит на самом деле? Вот какой-нить С++'овый инструмент вроде Valgrind'а бы помог. Только ставить Linux ради него не хочется. Мог бы помочь к-нить гуру :-) тока его хрен найдешь.

А может я где-то ошибаюсь в логике? У меня сильно смешана индексная и адресная арифметика, так что не все так просто, как кажется на первый раз. Возможно, следует перейти только к адресной.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

10. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от xhk Искать по авторуВ закладки on 04-Авг-05, 19:29  (MSK)
>Сами объекты создаются где-то вне массива с помощбю new(). А строчка
>>> delete items[index];
>возможно (это и есть первоначальный вопрос) будет удалять этот объект. Не массив
>указателей! Он удаляется в деструкторе.

Эта строка вообще не красива по сути. :) Вместо AnyType можно же подпихнуть и не класс, а можно вообще и не поинтер! В таком случае, что он вообще удалять то будет? Вы то, понятно, хотите туда пихать поинтер на класс, но самому классу DynArray это не известно. Тем более там нет проверки существования объекта по направлению самого поинтера.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

9. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от muxas emailИскать по авторуВ закладки(??) on 04-Авг-05, 15:58  (MSK)
И вообще realloc не самый лудший
>способ создания динамических массивов в плане производительности. Лучше выделять доп. куски
>памяти размером в страницу. Так куда эффективнее получитса.

Насчет эффективности я так рассуждал - любой вызов new\malloc\etc порождает системный вызов. Только new() еще дополнительно выполняет некий код. Плюс еще такой момент - если памяти не хватает, то что делать если пользуешся new()? Делать delete и затем еще один new()? Или складывать массив из связанного списка кусочков памяти? Тогда всю эффективность адресации при одном куске памяти нахрен придется послать.

Насчет кол-ва единовременно выделяемой памяти - сколько водки не бери все равно два раза бегать :-). Собственно говоря, страницы памяти под массив указателей возможно это очень много (смотря какая у вас страница). Размер указателя не очень большой. Однако это зависит от того для чего массивы использовать. Мне например нужно разместить результаты выборки из DВ. Там может быть и 5 строк и 100005. Так какой размер выбрать для единовременного выделения?

Короче, я решил, что нужно задавать шаг выделения памяти при создании массива. Он задается в конструкторе, в массиве он держится в nstep. Не самый лучший способ, но зато гибкий :-).

Есть идеи лучше? Поделитесь :-)

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

11. "Освобождение памяти в деструкторе шаблонного класса" 
Сообщение от xhk Искать по авторуВ закладки on 04-Авг-05, 19:31  (MSK)
>Есть идеи лучше? Поделитесь :-)

Просто realloc работает то не хитро. Он просто выделяет новую память, копирует туда все и удаляет старую. Это можно решить с помощью связанного списка из кусков памяти размером в страницу (для Linux размер страницы 4096, для Фрей - Гугль в помощь :) ). Когда в массиве будет нехватать памяти, просто выделяется дополнительно кусок памяти размером в страницу и указатель на нее пихается в список.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх


Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ]
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру