Cmap приводит к утечкам памяти
class CMapStringToATMRecord2 :
public CMap<CString*,CString*,CATMRecord,CATMRecord>
{
private:
public:
CMapStringToATMRecord2(void);
~CMapStringToATMRecord2(void);
};
CMapStringToATMRecord2 atms.
Собственно работаю примерно так:
CString str="разные значения в цикле проставляю"
CATMErrorRecord atmValue;
atms.SetAt(&str,&atmValue); // в этой строке помоему происходит утечка памяти
Я примерно представляю почему, по этому и сделал наследование от Cmap и в деструкторе попытался в ручную удалить все ключи и все значения вот так:
POSITION pos = GetStartPosition();
CString *key=NULL;
while(pos){
//CATMRecord atmValue;
GetNextAssoc(pos,key,atmValue);
//atmValue.~CATMRecord();
delete key;
};
};
Но такой деструктор память все таки не очищает, или очищает только ключи,
а вот если раскоментировать двестроки, то я так понимаю, уничтожение значений ячеек массива идет
Но дальше при выходе из деструктора видимо пытается вызваться настоящий родной деструктор CATMRecord atmValue и программа падает
Вобщем может кто подсказать решение чтобы минимально переделывая программу уже готовую избавиться от утечек памяти в Cmap структурах
з.ы. class CMapStringToShortInt2 : public CMap<CString*,CString*,short int,short int>
{
public:
CMapStringToShortInt2(void);
~CMapStringToShortInt2(void);
};
в таком классе я очищаю освобождаю память вот так:
CMapStringToShortInt2::~CMapStringToShortInt2(void)
{
POSITION pos = GetStartPosition();// освобождаем место от Cmap
CString *key=NULL;
short int val;
while(pos)
GetNextAssoc(pos,key,val),
delete key;
}
Вот ответь на два вопроса сначала.
- Зачем ты передаешь ключи по указателю, как ты потом будешь доступаться к данным? Для доступа нужен будет указатель на ту же самую область памяти, а не другой, пусть и содержащий такую же строчку.
- Зачем ты удаляешь в деструкторе память выделенную не внутри объекта. Кто выделял память перед тем как передать указатели в мап, тот и должен позаботится потом об удалении. Но никак не сам контейнер.
шаблоны которые позволят разрешить твой первый пункт, перегружается сравнение, и ключ находится который в другом куске памяти, но с такой же строкой
Проблема в том что выделение памяти идет вида:
Cstring *key = new....
map[key]=...
так вот удалить тут key нельзя)
Чтобы удалить нормально я использовал сначала так:
CString *mas[512];
mas = new CString(i);
map[mas] = ....
после использования мапа я удаляю в цикле ключи:
for(i=0;i<n;i++) delete mas
этот метод нормально очищал память когда в качестве знасчений были инты, ради интереса я его заменил перегруженным деструктором в первом посте по pos пробежал и удалил и тоже все ок
а вот когда значения классы такая штука не работает, а почему не работает я толком не понимаю из-за недостатка знаний, толи делит нужно делать ключам и значениям (т.е. два массива держать) то ли, я пробовал по разному но толком не вышло никак
В мсдн сказано что объекты значений сами должны удаляться при выходе за видимость, но вот толи я неправильно их инициализирую, толи не знаю что, вобщем память не очищается
Может попробывать сделать : CMap<CString*,CString*,CATMRecord*,CATMRecord*>?
map.SetAt(new CString("asds"),value);
При таком выделении же на эту область кроме как в мапе нигде ключи не храрнятся, разве они не должны освобождать при выходе за область видимости?
шаблоны которые позволят разрешить твой первый пункт, перегружается сравнение, и ключ находится который в другом куске памяти
Ну хорошо, добавил ты сравнение по указателям на строку но зачем? Если тебе нужны просто строковые ключи, почему ты хранишь там не сами экземпляры объектов строк, а указатели на них? Темболее что судя по твоей ссылке у них уже реализованно все необходимые сравнения (а если и не реализованны то можно их и добавить) и скорее всего конструктор копирования и оператор присваивания. В чем тайный смысл изобретать костыли, для ханения указателей, если можно использовать сами объекты в качестве ключей?
map.SetAt(new CString("asds"),value);
При таком выделении же на эту область кроме как в мапе нигде ключи не храрнятся, разве они не должны освобождать при выходе за область видимости?
Здесь ты выделяешь память вне объекта, а туда передаешь только указатель. Соотвественно когда эти данные больше не нужны - ты должен взять эти указатели из мапа и удалить их. Откуда мап может знать что там у него храниться и можно ли это вобще удалять в дестукторе - может у тебя эти указатели еще где то используются, не только в мапе.
гы... http://forum.codenet.ru/showpost.php?p=279126&postcount=5
Так не удаляются они сами
Переделал под CMapStringToObj
atms->SetAt(atmValue.terminalID.Trim(),(CObject*)new CATMRecord(&atmValue)); // утечка памяти в этом месте
[quote]{
CMapStringToOb map;
CAge age1(13); // Two objects on the stack
CAge age2(36);
map.SetAt(_T("Bart"), &age1);
map.SetAt(_T("Homer"), &age2);
ASSERT(map.GetCount() == 2);
map.RemoveAll(); // CObject pointers removed; objects not removed.
ASSERT(map.GetCount() == 0);
ASSERT(map.IsEmpty());
} // The two CAge objects are deleted when they go out of scope.
[quote]
это из мсдн, вот только реально они при выходе из области видимости почему-то не удаляются
Все удалется. В твоем примере ты хранишь не с ами оьбъекты, а указатели на них. Вот эти указатели и удаляются, а память куда они указывали - теряется. Если бы хранил сами экземпляры объектов строк в качестве ключей например, а не указатели - таких проблем бы не было.
так я вручную же вызываю delete для них
Вобщем сделал все аккуратно по тому принципу что описан выше, все стало ок) Всем спасибо.
Еще вопросик: если прога загружает библиотечку динамически, из библиотечки вызывается функция, в функции есть утечка памяти) то при выгрузке этой динамической библиотечки что происходит с той утерянной памятью? Она очищается или как? (прога остается в памяти, а библиотека только выгружается)
class CMapStringToATMRecord2 :
public CMap<CString*,CString*,CATMRecord,CATMRecord>
{
private:
public:
CMapStringToATMRecord2(void);
~CMapStringToATMRecord2(void);
};
CMapStringToATMRecord2 atms.
Собственно работаю примерно так:
CString str="разные значения в цикле проставляю"
CATMErrorRecord atmValue;
atms.SetAt(&str,&atmValue); // в этой строке помоему происходит утечка памяти
Я примерно представляю почему, по этому и сделал наследование от Cmap и в деструкторе попытался в ручную удалить все ключи и все значения вот так:
POSITION pos = GetStartPosition();
CString *key=NULL;
while(pos){
//CATMRecord atmValue;
GetNextAssoc(pos,key,atmValue);
//atmValue.~CATMRecord();
delete key;
};
};
Но такой деструктор память все таки не очищает, или очищает только ключи,
а вот если раскоментировать двестроки, то я так понимаю, уничтожение значений ячеек массива идет
Но дальше при выходе из деструктора видимо пытается вызваться настоящий родной деструктор CATMRecord atmValue и программа падает
Вобщем может кто подсказать решение чтобы минимально переделывая программу уже готовую избавиться от утечек памяти в Cmap структурах
з.ы. class CMapStringToShortInt2 : public CMap<CString*,CString*,short int,short int>
{
public:
CMapStringToShortInt2(void);
~CMapStringToShortInt2(void);
};
в таком классе я очищаю освобождаю память вот так:
CMapStringToShortInt2::~CMapStringToShortInt2(void)
{
POSITION pos = GetStartPosition();// освобождаем место от Cmap
CString *key=NULL;
short int val;
while(pos)
GetNextAssoc(pos,key,val),
delete key;
}
Для избежания подобного рода проблем юзай спец. утилиту для обнаружения утечек памяти. Например Deleaker.
http://deleaker.ru