[c++] утечка памяти при работае с vector <T>

koly

Есть примерно такой код:

class SomeClass {
public:
vector <T> v;
SomeClass {
v=vector<T>
};
~SomeClass {
v.clear;
}
}
...
int main (...) {
for (...) {
SomeClass a = SomeClass;
a.v.push_back(...);
}
}

valgrind показывает, что память, выделенная в a.v.push_back течет.
Как правильно освобождать вектор, чтобы не было утечек?

kruzer25

Сообщение удалил

koly

не надо. v - это не ссылка

ppplva

v=vector<T>
Замечательный стиль.
Может течет не в push_back, а в троеточии ?

evgen5555

Очевидно, в деструкторе T что-то недоразрушается.

evgen5555

Ну и типа перед входом в конструктор SomeClass вектор уже инициализировался, а внутри создается уже второй вектор.

koly

в троеточии стековый объект находится. Насчет стиля - как было бы лучше? (в реальном коде есть typedef vector <T> SomeType; )

koly

Ну и типа перед входом в конструктор SomeClass вектор уже инициализировался, а внутри создается уже второй вектор.
Не забывай, что это с++, а не c#

kokoc88

Напиши, какой есть код, не примерно.

koly

Кода многовато.
Вопрос основной вот в чем.
Если объект класса SomeClass освобождается, то, очевидно, он должен явным образом освобождать вектор, являющийся его полем.
Вопрос в том, как правильно освободить вектор?

kokoc88

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

evgen5555

Вот что в стандарте говорят (12.6.2.5 обрати внимание на последний и предпоследний пункты.
Initialization shall proceed in the following order:
First, and only for the constructor of the most derived class as described below, virtual base classes shall be initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where ``left-to-right'' is the order of appearance of the base class names in the derived class base-specifier-list.
Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
Finally, the body of the constructor is executed.

koly

Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
Finally, the body of the constructor is executed.
Ты знаешь, что означают слова "shall be initialized " ?
Вот, что:
SomeClassConstructor::SomeClassConstructor :field1(value1 field2(value2) {
}

koly

Код main:

int main(int argc, char* argv[])
{
if (argc != 2) {
cout << "Usage: recognition 24bit_bmp_filename" << endl;
exit(-1);
}
char * bmpfile;

bmpfile = argv[1];
Bmp bmp (bmpfile);
ColorFilter::init(bmp.width, bmp.height);
BlobRecognitionFilter::init(bmp.width, bmp.height);
for (int i=0; i<2; i++ ){
cout << "Frame number " << i << endl;
Blobs2Objects b2o= Blobs2Objects;
ColorFilter colorFilter(&bmp);
char * names[5]={"RED","GREEN","BLUE","WHITE","BLACK"};
for (int color=0; color<5; color++) {
cout << "Channel name = " << names[color]<< endl;
try {
Channel * channel = colorFilter.channel[color];
// channel->saveChannel(string(bmpfile) + ".filtered."+string(names[color])+".bmp");
BarierFilter barierFilter(colorFilter.channel[color], 10);
// channel->saveChannel(string(bmpfile) + ".filtered."+string(names[color])+".barier.bmp");
BlobRecognitionFilter blobRecognitionFilter(colorFilter.channel[color]);
// blobRecognitionFilter.saveBmpRecognized(string(bmpfile) + ".filtered."+string(names[color])+".recognition.bmp");
b2o.addBlobData(blobRecognitionFilter.blob, color);
} catch (FilterException ex) {
cerr << "Error in filter " << ex.getFilterName;
}
}
vector <PolygonObject> balls ;
balls = b2o.blackBalls;
cout << "*** BLACK BALLS ***" << endl;
for (unsigned i=0; i<balls.size; i++) {
cout << balls[i] << endl;
}
balls = b2o.whiteBalls;
cout << "*** WHITE BALLS ***" << endl;
for (unsigned i=0; i<balls.size; i++) {
cout << balls[i] << endl;
}
vector <PolygonObject> holes ;
holes = b2o.redHoles;
cout << "*** RED HOLES *** " << endl;
for (unsigned i=0; i<holes.size; i++) {
cout << holes[i] << endl;
}
holes = b2o.blueHoles;
cout << "*** BLUE HOLES *** " << endl;
for (unsigned i=0; i<holes.size; i++) {
cout << holes[i] << endl;
}
cout << endl;
}
ColorFilter::dispose;
BlobRecognitionFilter::dispose;
cout << endl;
return 0;
}

Код класса Blobs2Objects

#include "filters/BlobData.h"
#include <vector>
#include <iostream>
#include <sstream>
#include "Bmp.h"
using namespace std;
struct PolygonObject {
int x, y;
int color;
string ToString;
};
ostream & operator << (ostream & o, PolygonObject &obj) ;
typedef vector <PolygonObject> PolygonObjects;
class Blobs2Objects {
public:
PolygonObjects whiteBalls;
PolygonObjects blackBalls;
PolygonObjects redHoles;
PolygonObjects blueHoles;
// *********************


Blobs2Objects ;
~Blobs2Objects;
void addBlobData(vector <BlobData> &blobData, int color);
PolygonObjects *getHoles;
PolygonObjects *getBalls;
};
Blobs2Objects ::Blobs2Objects :whiteBalls blackBalls redHoles blueHoles {
}
string PolygonObject::ToString{
string str;
ostringstream s;
s << color << string(" ") << x << string(" ") << y;
str = s.str;
return str;
}
ostream & operator << (ostream & o, PolygonObject &obj) {
o << obj.color << " " << obj.x << " " << obj.y ;
return o;
}
void Blobs2Objects::addBlobData(vector <BlobData> &pvblobData, int color){
for (unsigned i=0; i<pvblobData.size; i++) {
BlobData *pblobData = &pvblobData[i];
PolygonObject obj =PolygonObject;
obj.color = color;
obj.x = pblobData->centerX;
obj.y = pblobData->centerY;
switch (color) {
case WHITE:
if (pblobData->size > 10) {
whiteBalls.push_back(obj);
}
break;
case BLACK:
if (pblobData->size > 10) {
blackBalls.push_back(obj);
}
break;
case RED:
if (pblobData->size > 10) {
redHoles.push_back(obj);
}
break;
case BLUE:
if (pblobData->size > 10) {
blueHoles.push_back(obj);
}
break;
}
}
}
Blobs2Objects::~Blobs2Objects {
whiteBalls.clear;
blackBalls.clear;
redHoles.clear;
blueHoles.clear;
}

kokoc88

Не обязательно. Остальные члены тоже будут инициализированны по умолчанию.

koly

Утечка в таких местах :
whiteBalls.push_back(obj);

ppplva

Вот, что:
SomeClassConstructor::SomeClassConstructor :field1(value1 field2(value2) {
}

Это - чем они будут инициализированы.
Если не указать, они проинициализируются дефолтными значениями. Что у тебя и происходит - выполняется сначала дефолтный конструктор от вектора, потом еще один, потом operator =.
А по приведенному коду ничего не понятно. Можешь написать небольшой пример, который компилируется и показывает утечку памяти ?

kokoc88



valgrind показывает, что память, выделенная в a.v.push_back течет.
Хмм, а может valgrind считает утечкой, что ты перед выходом из программы сам не очищаешь вектор? У тулов для дебага бывают некоторые проблемы от ума.

koly

Чуваки! Когда вы последний раз писали на с++ ?
Повторяю, это С++, а не с# и не java!
Трудно с вами разговаривать...
вот код, который я предлагаю скомпилировать всем упертым, чтобы убедиться, что поля НЕ инициализируются перед вызовом конструктора:
#include <iostream>
using namespace std;
class SomeClass1 {
public:
SomeClass1 { cout << "'ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!" << endl;};
};
class SomeClass {
public:
int a[100];
SomeClass1 c;

};
int main(int argc, char* argv[])
{
SomeClass b;

for (int i=0; i<100; i++) {
cout << b.a[i] << " " ; // В ЭТИХ ПЕРЕМЕННЫХ МУСОР!
}
}

bobby

Post deleted by

kokoc88



#include <iostream>
using namespace std;
class SomeClass1 {
public:
SomeClass1 :value(0){ cout << "'ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!" << endl;};
};
На С++ пишу прямо сейчас. Твой код не компилируется.

bobby

Вообще-то, твой код последний даже не компилируется, т.к. там какое-то value, которого нет.
Если это убрать, то конструктор SomeClass1, разумеется, вызовется.

bobby

Да, а в переменных a[i], разумеется, мусор!

koly

да, уже исправился.
Ну, кто-нибудь запустил?

bobby

Я запустил, а ты?

koly

сейчас компилируется

kokoc88

И я запустил. И увидел "ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!"

bobby

+1

bleyman

И увидел "ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!"
Не верь глазам своим!

koly

Понятно, мы пишем на разных языках. У меня видимо, компилируется по прошлому стандарту и я отстал от времени
зы у меня visual c++ 7.0
Только что попробовал на g++ 3.3.5 и конструктор вызвался

bobby

Дык в VC 7.0, может быть, и реализация STL тупая, с утечками памяти.
Переходите на 7.1 =)

koly

но тут такая штука - я то утечку нашел на valgrind, предварительно скомпилировав в g++ 3.3.5, который, видимо по умолчанию очень близок к стандарту и достаточно безглючен в сравнении с тем же vc++

okunek

уж лучше сразу тогда на 8

bobby

С 7.0 на 7.1 перейти проще, чем на 8.0, имхо =)

bobby

Ну, это плохо, конечно.

kokoc88

Это будет работать на любом VS, от 5-го до 8-го.

okunek

зато некошерно

koly

на конкретно моем 7.0.9466 конструктор SomeClass1 не вызывается

kokoc88

Ты опять что-то не так написал. Это работает даже на пятой студии.

evgen5555

[vhost ~]$ ./a.out
'ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!
134513671 -1075119928 2516546 134513164 -1075119996 2573904 4 -1208551288 1 0 1 2572212 7313025 7819936 2573904 7313229 7837300 1 -1075119996 7305636 -1075119996 -1 -1075120024 7305768 7837300 -1 0 7307242 7819936 0 64971124 -1075119888 2573560 1 -1075119960 7387007 7840360 2616872 -1208552168 7837952 -1075119928 7838800 7838692 7819936 7838692 7837824 -1075119928 7387245 7838692 7838800 7387207 2572212 2573560 1 -1075119872 2529974 2573988 -1208551288 1 1 0 134519956 5 134513671 2616872 134519680 0 2758294 -1075119816 3776500 0 -1075119848 2758532 134519680 -1075119816 134514821 134514826 0 134519992 2575240 1 -1075119764 -1075119784 134514871 1 65535 24641422 -1075119664 2573560 613 -1075119768 134515165 3781496 134519932 -1075119752 134514017 19527 15 -1075119720 134515014
[vhost ~]$ g++ --version
g++ (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[vhost ~]$

evgen5555

Может, компилируешь не то, или не то запускаешь?

mira-bella

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

mira-bella

Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
Finally, the body of the constructor is executed.
Ты знаешь, что означают слова "shall be initialized " ?
Вот, что:
SomeClassConstructor::SomeClassConstructor :field1(value1 field2(value2) {
}
нет
"shall be initialized" означает вызов нужного конструктора во время выполнения твоей проги (так обозначается процесс, выполняемый прогой, а не какая-то часть ее текста)
а то, что ты написал - "field1(value1 field2(value2)" - это пример "mem-initializers", упомянутых в тексте утверждением, что от их порядка не зависит порядок инициализации нестатических членов класса.

mira-bella

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

rosali

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

ты б книжек что ли почитал?..

erotic

 
Ну и типа перед входом в конструктор SomeClass вектор уже инициализировался, а внутри создается уже второй вектор.

Кому это мешает? Он создается пустой, копируется в v, а затем уничтожается. Ничего страшного. Другое дело, что нахуй не нужно.

evgen5555

Это к слову о стиле, вообще-то.

Russula

помнится, я читал документацию по STLPort и там оин из макросов в зависимости от того, был он определен или нет, определял - будут псевдо утечки памяти с точки зрения некоторых утилит или нет. Та же самая проблема у меня была со string'ом. Мне говорили, что утечка памяти. На самом деле ее нет
Оставить комментарий
Имя или ник:
Комментарий: