Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 21, средняя оценка - 4.81
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
#1

течь памяти из вектора - C++

30.05.2011, 19:51. Просмотров 2543. Ответов 30

всем добрый вечер. постарайтесь не критиковать сразу новичка. столкнулся со странным явлением
при выполнении заданий по Страуструпу. создана простая рисовалка (все на API), есть базовый объект shape и фигуры от него унаследованные. есть вектор <shape*>, создаются фигуры и помещатся в вектор.
хрянятся там, перерисовываюся (делал для пущего эксперименту интрузивный список, простой проще некуда, но это отступление), так вот, все хорошо рисуется, при уничтожении окна корректно все объекты разрушаются, память осв.(проходом по вектору указателей командой delete). и вот дальнейшее развитие - некое подобие "стрелялки", рисуется объект, а далее "выстрел", по экрану движется окружность, при достижении объекта - объект удаляется( а именно прибивается в векторе), все работает отлично, после закрытия проги все чисто. НО, все хорошо кроме объекта curve, который представяет собой последовательность объектов line. Понимаю что звучит абстрактно, уточню. line - это протсо две точки и линия меж ними, curve это vector <shape*> добавляющий в себя линии по мере движения мыши и в итоге, когда левая клавиша ап, curve добавляется к вектор <shape*> основного объекта. тиак вот повторю все нормально рисутеся и удаляется на выходе, далее все объекты (кроме курвы) при выстреле удаляются и при выходе не дают течи, но при попытке удалить curve, удаление происходит успешно но на выходе имеется утечка памяти. ОТКУДА? что течет. деструктор вызыватся правильно, список внутри curve очищается, внешний список тоже, короче все в дебаге по шагам прошел. все удаляется. откуда течь? может есть супер особенность вектора? о которой я знать не знаю. подскажите
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.05.2011, 19:51
Здравствуйте! Я подобрал для вас темы с ответами на вопрос течь памяти из вектора (C++):

Удаление вектора из области динамической памяти. - C++
Всем привет! Прошу разъяснить. Как правильно удалить содержимое вектора? class Coordinate { public: Coordinate() {} int...

Динамическое выделение памяти для Вектора ( не STL) - C++
привет Ребят, Задание таково, прога читает слова из файла и в зависимости от выбора опций показывает мне количество уникальных слов,...

Ошибка при резервировании памяти для своего(!) вектора - C++
Всем здравствуйте! Возможно, из названия темы не совсем понятен вопрос, поэтому уточню саму суть: Пишу свой шаблонный класс вектора и...

Найти сколько элементов первого вектора совпадают с элементами второго вектора - C++
#include &lt;iostream&gt; #include &lt;time.h&gt; #include &lt;vector&gt; #include &lt;set&gt; using namespace std; void main() { ...

Дан список, элементы которого являются координатами вектора. Найти длину вектора - C++
1. Дан список, элементы которого являются координатами вектора в n-мерном пространстве. Найти длину вектора.

Определить количество положительных элементов вектора С(10) и заменить этим значением минимальный элемент вектора А(5) - C++
Ребята помогите пожалуйста с задачкой. Я сам не шарю в C++, но в этом семестре появился этот предмет! И завтра его надо будет сдать :( Буду...

30
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
30.05.2011, 20:01 #2
Без контекста выделения и возврата памяти сказать невозможно. Текст - в студию.
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
30.05.2011, 21:55  [ТС] #3
постараюсь дать общую идею, так как все вкатать это ужос.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "shape.h" //здесь абстрактный класс фигуры
 
class S //это некий управляющий класс, управляет очередями сообщений заодно и отрисовкой
{
 
public:
vector<shape*> VEC // вектор содержит указатели на фигуры производные от shape - они и перерисовываются по WM_PAINT
 
S(){};
 
~S()
 {
 for(int i=0;i<VEC.size();i++)
  delete VEC[i];
 VEC.clear();
 };
}
 
 
class curve: public shape
{
public:
vector<shape*> V2;
curve(){};
~curve()
 {
 for(int i=0;i<V2.size();i++)
  delete V2[i];
  V2.clear();
 }
}
 
//привел только деструкторы дабы не громоздить и показать как очищаю векторы
//ниже создание объектов, приведу некую абстрактную функцию.
 
void make()
{
S s;
 
//создание простых фигур через конструкцию switch в ответ на выбор меню, цвета там и пр и 
//движение мыши.
//  указатели заталкиваюся в вектор класса S после того как левая клавиша отпущена.
shape* figure = new line();
s.VEC.push_back(figure);
shape* figure = new circle();
s.VEC.push_back(figure);
//в конструкторах фигур, координаты, цвет, толщина пера, тип, HRGN полигон(для определения 
//пересечений), ничего динамического, ну а ниже собственно создание curve
figure = new curve()// этот конструктор и в реале пустой
//на движение мыши 
curve.addsegment() - сюда передаются все параметры как для создания линии, координаты и пр.
//левая клавиша отжата и curve добавляется в общий вектор
s.VEC.push_back(figure)
}
 
curve.addsegment()
{
shape8 temp = new line();
V2.push_back(temp);// курва это просто набор простых линий
}
 
//расписывать рисование думаю нет смысла. итак камень преткновения
//при такой схеме все работает, рисуется удаляется, чисто.
//выстрел - летящий круг пересекает регион объекта в векторе и по этому принципу объект 
//удаляется из вектора, для простых фигур вполне прокатывает delete s.VEC[i];s.VEC[i]=0;// нет течи
//думаю не совсем верно это поскольку остается пустая ячейка в векторе
// для курвы - и удалял через *iterator, и через delete + erase() ,и через приведение указателя //shape* к curve*, и вызывал //~curve() не советуют так делать (почему?) . деструкторы 
//вызываются, все ок, объекты 
//уничтожаются, НО на выходе - течь. Стреляешь не в курву - нет течи. А с курвой прям беда.
//
сейчас я отправлю сообщение. Я новичок и оно может быть оформлено неверно. Ужо не судите. Постарался объяснить суть.

 Комментарий модератора 
Используйте теги форматирования кода!
0
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
30.05.2011, 22:11 #4
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "shape.h" //здесь абстрактный класс фигуры
 
class S //это некий управляющий класс, управляет очередями сообщений заодно и отрисовкой
{
 
public:
vector<shape*> VEC // вектор содержит указатели на фигуры производные от shape - они и перерисовываются по WM_PAINT
 
S(){};
 
~S()
{
for(int i=0;i<VEC.size();i++)
delete VEC[i];
VEC.clear();
};
}
 
 
class curve: public shape
{
public:
vector<shape*> V2;
curve(){};
~curve()
{
for(int i=0;i<V2.size();i++)
delete V2[i];
V2.clear();
}
}
 
 
//привел только деструкторы дабы не громоздить и показать как очищаю векторы
//ниже создание объектов, приведу некую абстрактную функцию.
 
void make()
{
S s;
 
//создание простых фигур через конструкцию switch в ответ на выбор меню, цвета там и пр и
//движение мыши.
// указатели заталкиваюся в вектор класса S после того как левая клавиша отпущена.
shape* figure = new line();
s.VEC.push_back(figure);
shape* figure = new circle();
s.VEC.push_back(figure);
//в конструкторах фигур, координаты, цвет, толщина пера, тип, HRGN полигон(для определения
//пересечений), ничего динамического, ну а ниже собственно создание curve
figure = new curve()// этот конструктор и в реале пустой
//на движение мыши
curve.addsegment() - сюда передаются все параметры как для создания линии, координаты и пр.
//левая клавиша отжата и curve добавляется в общий вектор
s.VEC.push_back(figure)
}
 
curve.addsegment()
{
shape* temp = new line();
V2.push_back(temp);// курва это просто набор простых линий
}
 
//расписывать рисование думаю нет смысла. итак камень преткновения
//при такой схеме все работает, рисуется удаляется, чисто.
//выстрел - летящий круг пересекает регион объекта в векторе и по этому принципу объект
//удаляется из вектора, для простых фигур вполне прокатывает delete s.VEC[i];s.VEC[i]=0;// нет течи
//думаю не совсем верно это поскольку остается пустая ячейка в векторе
// для курвы - и удалял через *iterator, и через delete + erase() ,и через приведение указателя //shape* к curve*, и вызывал //~curve() не советуют так делать (почему?) . деструкторы
//вызываются, все ок, объекты
//уничтожаются, НО на выходе - течь. Стреляешь не в курву - нет течи. А с курвой прям беда.
//
Во-первых, меня смущает:
C++
1
curve.addsegment()
Ведь у тебя указатель. Поэтому figure->addsegment() надо писать.
Во-вторых, у тебя добавляется в вектор и figure для curve, и внутри addsegment() еще создается один динамический объект и тоже добавляется в вектор.
В-третьих, при удалении фигуры, ты память освобождаешь, но из вектора не удаляешь элемент, а просто обнуляешь его.
А потом в деструкторе еще раз вызывается возврат памяти.
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
30.05.2011, 22:58  [ТС] #5
да конечно. -> сорри это тут видимо спешил. все верно вектор в нем указатели на объекты, внтури curve - тоже вектор тоже с указателями на объекты в куче. признаю ошибку по поводу обнуления элемента основного вектора, но разве при выходе из программы и разрушении вектора - не будет удален и этот нулевой, пустой элемент?
далее. я пробовал и erase(), т.е. не было пустых элементов. Обнуление делал для того чтобы работали условия такого плана if(!s.VEC[i]) что то делаем.

дошло до того что я стал создавать только одну фигуру curve и удалять ее delete s.VEC[i]; далее затирать данную позицию erase() или еще лучше s.VEC.clear(); вектор показывал что его размер 0, до трюков со сжатием я еще не дошел, и его объем остался 1.
и....при закрытии течь.
постараюсь выделить главное.
1. проверка показала что при delete s.VEC[i] вызыватся ~curve() и внутренний список очищается.
значит curve чиста, течь не в ней так? (при простом рисованиии все списки удаляются по той же схеме и течи нет, т.е. я нарисовал дом, траву и людей, создал с десяток curve и при закрытии окна вызваются эти 10 ~curve() и все чисто)
2. именно при попытке удалить искуственно элемент общего вектора и именно если этот элемент curve, при закрытии память утекает
Detected memory leaks!
Dumping objects ->
{234} normal block at 0x003661C0, 8 bytes long.
Data: < {6 > D4 7B 36 00 00 00 00 00
{233} normal block at 0x00367BA0, 72 bytes long.
Data: < B > B4 E9 42 00 CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Я так понимаю вопрос можно свести к такому. как правильно удалить объект используя указатель на него хранящийся в любой части вектора, при условии что объект в куче и сам внутри содержит вектор указателей на объекты кучи.Что из того что я написал в деструкторах не работает?

Добавлено через 15 минут
Валерий, может у меня глаз замылился и не понимаю чего то элементарного?
на каждый new объект приходится и delete. и при последовательном очищении как, внешнего так и внутреннего вектора(curve) все хорошо. но стоит "выстрелом" удалить вручную элемент вектора и если этот элемент curve то вот такая беда.
0
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
30.05.2011, 23:53 #6
Цитата Сообщение от AzaKendler Посмотреть сообщение
Валерий, может у меня глаз замылился и не понимаю чего то элементарного?
на каждый new объект приходится и delete. и при последовательном очищении как, внешнего так и внутреннего вектора(curve) все хорошо. но стоит "выстрелом" удалить вручную элемент вектора и если этот элемент curve то вот такая беда.
Прежде, чем саму курву удалять не нужно ли удалить все внутренние у нее объекты? Как я понимаю, ты там тоже делаешь new(). Поэтому нужно сначала сделать delete() для всех таких объектов, а потом уже curve делать erase. Иначе - потерянные ссылки возникают - та самая утечка памяти...
0
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
31.05.2011, 00:19 #7
auto_ptr спасет отца русской демократии?
0
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
31.05.2011, 00:25 #8
Цитата Сообщение от lemegeton Посмотреть сообщение
auto_ptr спасет отца русской демократии?
Ну, или другой интеллектуальный указатель, например shar_ptr
0
slice
35 / 78 / 4
Регистрация: 04.11.2010
Сообщений: 249
31.05.2011, 00:28 #9
нубасы, я по первому посту догадался, что автор забыл виртуальный деструктор
1
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
31.05.2011, 08:45 #10
Цитата Сообщение от slice Посмотреть сообщение
нубасы, я по первому посту догадался, что автор забыл виртуальный деструктор

Не по теме:

Так вот ты какой - Северный Олень!

0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.05.2011, 12:31  [ТС] #11
спасибо всем за ответы огромное. но хочу уточнить. объекты внутри курвы удаляются в ее деструкторе. тут все ок. т.е. когда она дергается на удаление из основного списка - вызывается ее деструктор, а в нем чистится внутренний список. Это касается и виртуальных деструкторов - я проверял - вызывается именно нужный деструктор, ~curve() и в нем чистится список содержащий линии составляющие кривую.
поскольку все объекты стремятся разрушится на выходе из проги, то дергаются деструкторы в которых я очищаю то, что насоздавал в куче. повторю что при простом рисовании - создай хоть 50 curve, каждая из сотен сегментов - на выходе все чисто. Проблем именно с удалением из вектора по позиции.
Или я не уловил совет? Предлагается принудительно очистить списоk curve? он ведь и так в деструкторе чистится.

по поводу auto_ptr - каюсь, я новичок и не дочитал еще до них. Уже жалею что переделал все на вектор вместо своего интрузивного списка, там было все очень просто и видно что почем, но была другая причина почему я переделал на вектор(это отдельная тема, хотел проверить кое что). пока непонятно в чем причина. буду тестировать сегодня еще. Это тестовая прога так сказать, никаких бизнес критикал, но прсто очень хочется понимания а не так все бросить и дальше что то делать.

Добавлено через 1 час 43 минуты
в общем то выписанные на бамажку адреса указателей дали следующее

{187} normal block at 0x00366158, 8 bytes long.
Data: <Lo6 > 4C 6F 36 00 00 00 00 00
{186} normal block at 0x00366F18, 72 bytes long.
Data: < B > B4 E9 42 00 CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

оба объекта по адресам расположены в пределах куска памяти под curve.

второй объект это ВСЕГДА некий "несуществующий" объект находящийся за пределами последнего элемента вектора. например я создал 38 элементов а на выходе получил течь с адресом 39-го, создал 39 - получил течь адреса 40-го, это немного странно.
учитывая что новые элементы добавляются к вектору только стандартными операциями push никакого случайного добавления быть не может.

по первому адресу непонятно - он лежит в диапазоне куска выделенного под curve где то между 7 и 8 элементом. с чего бы это?

вся данная ситуация только при попытке ручного удаления curve из основного вектора.
1
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
31.05.2011, 18:06 #12
AzaKendler, а поставь-ка ты в конструкторы и деструкторы диагностическое сообщение. И смотри, не создаются ли у тебя временные объекты.
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.05.2011, 19:43  [ТС] #13
Валерий, в битве СТАНДАРТОВ и человека, победили СТАНДАРТЫ), вектор оказался ни при чем, в одном из обработчиков мыши я нашел баг, именно при таком сочетании создавался пустой curve и помещался в вектор, он и тек. Добавил условие и все. Прекрасный язык С++, приучает к вниманию в мелочах и деталях. И не так страшен чОрт ка его малюют, стоит сесть и еще более внимательно проанализировать и вот, нате. Ошибочка.
Спасибо что выслушали и я рад, что зарегился на таком отличном форуме!
1
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
31.05.2011, 19:49 #14
AzaKendler, диагностические сообщения в конструкторах - рулят! Сразу видать лишние вызовы конструкторов. А если еще макросы _LINE_ и _FILE_ использовать, то вообще отличная диагностика выходит!
1
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.05.2011, 19:54  [ТС] #15
Я пока не успел ими воспользоваться.Увидел поздновато. Но теперь буду знать, сэкономил бы время.
Задам параллельно вопрос - насколько я понял количество HDC в WIndows ограничено, а как сократить создание контекстов? Передавать ссылки? НDC - это по моему и так указатель.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.05.2011, 19:54
Привет! Вот еще темы с ответами:

Ошибка с итераторами для целочисленного вектора и вектора структуры - C++
Пытаюсь разобраться с векторами. Для динамической работы с памятью вещь, вроде, замечательная и удобная. Только необходимо использовать...

Составить главную программу и функцию. Для данного вектора А(М) найти количество неповторяющихся элементов вектора - C++
Здравствуйте. Буду очень благодарен,если кто нибудь напишет два кода к этим задачам. Спасибо за внимание. Задача 1. Составить...

Заданный вектор А, состоящий из n элементов. Переставить компоненты вектора, размещенные после самого элемента вектора А - C++
Заданный вектор А, состоящий из n элементов. Переставить компоненты вектора, размещенные после самого элемента вектора А на начало, а...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
31.05.2011, 19:54
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru