[c++] утечка памяти при работае с vector <T>
Сообщение удалил
не надо. v - это не ссылка
v=vector<T>Замечательный стиль.
Может течет не в push_back, а в троеточии ?
Очевидно, в деструкторе T что-то недоразрушается.
Ну и типа перед входом в конструктор SomeClass вектор уже инициализировался, а внутри создается уже второй вектор.
в троеточии стековый объект находится. Насчет стиля - как было бы лучше? (в реальном коде есть typedef vector <T> SomeType; )
Ну и типа перед входом в конструктор SomeClass вектор уже инициализировался, а внутри создается уже второй вектор.Не забывай, что это с++, а не c#
![](/images/graemlins/smile.gif)
Вопрос основной вот в чем.
Если объект класса SomeClass освобождается, то, очевидно, он должен явным образом освобождать вектор, являющийся его полем.
Вопрос в том, как правильно освободить вектор?
В твоём случае он себя сам освобождает. Как уже отметили выше, мемори лики могут быть только если хранимый класс что-то не освобождает в деструкторе. Покажи код, без этого ничего не понять.
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.
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).Ты знаешь, что означают слова "shall be initialized " ?
Finally, the body of the constructor is executed.
Вот, что:
SomeClassConstructor::SomeClassConstructor :field1(value1 field2(value2) {
}
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;
}
Не обязательно. Остальные члены тоже будут инициализированны по умолчанию.
whiteBalls.push_back(obj);
Вот, что:
SomeClassConstructor::SomeClassConstructor :field1(value1 field2(value2) {
}
Это - чем они будут инициализированы.
Если не указать, они проинициализируются дефолтными значениями. Что у тебя и происходит - выполняется сначала дефолтный конструктор от вектора, потом еще один, потом operator =.
А по приведенному коду ничего не понятно. Можешь написать небольшой пример, который компилируется и показывает утечку памяти ?
Хмм, а может valgrind считает утечкой, что ты перед выходом из программы сам не очищаешь вектор? У тулов для дебага бывают некоторые проблемы от ума.
valgrind показывает, что память, выделенная в a.v.push_back течет.
Повторяю, это С++, а не с# и не 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] << " " ; // В ЭТИХ ПЕРЕМЕННЫХ МУСОР!
}
}
Post deleted by
На С++ пишу прямо сейчас. Твой код не компилируется.
#include <iostream>
using namespace std;
class SomeClass1 {
public:
SomeClass1 :value(0){ cout << "'ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!" << endl;};
};
Если это убрать, то конструктор SomeClass1, разумеется, вызовется.
Да, а в переменных a[i], разумеется, мусор!
Ну, кто-нибудь запустил?
Я запустил, а ты?
сейчас компилируется
![](/images/graemlins/smile.gif)
![](/images/graemlins/lol.gif)
И увидел "ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!"Не верь глазам своим!
![](/images/graemlins/smile.gif)
зы у меня visual c++ 7.0
Только что попробовал на g++ 3.3.5 и конструктор вызвался
Переходите на 7.1 =)
но тут такая штука - я то утечку нашел на valgrind, предварительно скомпилировав в g++ 3.3.5, который, видимо по умолчанию очень близок к стандарту и достаточно безглючен в сравнении с тем же vc++
![](/images/graemlins/smile.gif)
С 7.0 на 7.1 перейти проще, чем на 8.0, имхо =)
Ну, это плохо, конечно.
Это будет работать на любом VS, от 5-го до 8-го.
![](/images/graemlins/smile.gif)
![](/images/graemlins/smile.gif)
Ты опять что-то не так написал. Это работает даже на пятой студии.
'ЭТОТ КОНСТРУКТОР НЕ ВЫЗЫВАЕТСЯ!
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 ~]$
Может, компилируешь не то, или не то запускаешь?
Если объект класса SomeClass освобождается, то, очевидно, он должен явным образом освобождать вектор, являющийся его полем.это не только не очевидно, но и неверно, если речь о деструкторе
т.к. очевидно для всех полей класса вызываются деструкторы после выполнения тела деструктора класса (в порядке обратном вызову конструкторов, при вызове конструктора класса)
вообще в твоем первом сообщении и конструктор и деструктор совершенно лишние
нет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).Ты знаешь, что означают слова "shall be initialized " ?
Finally, the body of the constructor is executed.
Вот, что:
SomeClassConstructor::SomeClassConstructor :field1(value1 field2(value2) {
}
"shall be initialized" означает вызов нужного конструктора во время выполнения твоей проги (так обозначается процесс, выполняемый прогой, а не какая-то часть ее текста)
а то, что ты написал - "field1(value1 field2(value2)" - это пример "mem-initializers", упомянутых в тексте утверждением, что от их порядка не зависит порядок инициализации нестатических членов класса.
У меня видимо, компилируется по прошлому стандарту и я отстал от временинет, у тебя компилируется вообще не по стандарту, т.к. в самом первом официальном стандарте уже все должно инициализироваться
Если объект класса SomeClass освобождается, то, очевидно, он должен явным образом освобождать вектор, являющийся его полем.
![](/images/graemlins/crazy.gif)
Ну и типа перед входом в конструктор SomeClass вектор уже инициализировался, а внутри создается уже второй вектор.
Кому это мешает? Он создается пустой, копируется в v, а затем уничтожается. Ничего страшного. Другое дело, что нахуй не нужно.
Это к слову о стиле, вообще-то.
помнится, я читал документацию по STLPort и там оин из макросов в зависимости от того, был он определен или нет, определял - будут псевдо утечки памяти с точки зрения некоторых утилит или нет. Та же самая проблема у меня была со string'ом. Мне говорили, что утечка памяти. На самом деле ее нет
Оставить комментарий
koly
Есть примерно такой код:valgrind показывает, что память, выделенная в a.v.push_back течет.
Как правильно освобождать вектор, чтобы не было утечек?