Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Утечка памяти... ничего не могу поделать :( 
:(
    Опции темы
kometa_triatlon
Дата 26.11.2005, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 384
Регистрация: 7.1.2005
Где: Киев

Репутация: 1
Всего: 6



У меня такая ситуация сложилась...
У меня есть коллекция объектов (тип CObArray ) моего типа CVarItem.
В процессе работы программы я добавляю в него новые объекты:
Код

CVarItem* pItem = new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]);
        m_arrVarList.Add(pItem);

Вот только при этом получаются бешеные утечки памяти, потому что я ее не освобождаю.
Если освобождаю:
Код

CVarItem* pItem = new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]);
        m_arrVarList.Add(pItem);
        delete pItem;

то вылетаю с exception 0xC0000005: Access violation reading location 0xfeeefeee.
Ничего не могу понять, я что, лезу куда-то не туда в память??
Полный код функции вот:
Код

void CanalyserApp::GetVarsFromInit(CString strVars, VARSTATE state, int iLine, char lpszType[10], CString strSubProgName )
{
    int iStart = 0;
    char szTokens[] = _T(" ,\n\t\r:");

    CString strToken = strVars.Tokenize(szTokens, iStart);
    while( strToken != "" )
    {
        CVarItem* pItem = new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]);
        m_arrVarList.Add(pItem);
        strToken = strVars.Tokenize(szTokens, iStart);

    }    
}



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

--------------
Программирование - самое большое удовольствие, которое вы можете получить, будучи одетым.
PM MAIL ICQ   Вверх
Mad
Дата 26.11.2005, 00:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 2
Всего: 19



Цитата(kometa_triatlon @ 25.11.2005, 23:49)
Если освобождаю:
то вылетаю с exception 0xC0000005: Access violation reading location 0xfeeefeee.
Ничего не могу понять, я что, лезу куда-то не туда в память??


Цитата(kometa_triatlon @ 25.11.2005, 23:49)
У меня есть коллекция объектов (тип CObArray ) моего типа CVarItem.

Замени на CPtrArray, только не забуть потом удалить эти обьекты (когда они уже будут не нужны)


--------------------
user posted image
PM MAIL   Вверх
kometa_triatlon
Дата 26.11.2005, 01:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 384
Регистрация: 7.1.2005
Где: Киев

Репутация: 1
Всего: 6



Mad
Заменил, то же самое .... smile


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

--------------
Программирование - самое большое удовольствие, которое вы можете получить, будучи одетым.
PM MAIL ICQ   Вверх
Mad
Дата 26.11.2005, 03:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 2
Всего: 19



kometa_triatlon
А тебе обязательно нужен дву-направленный список ? (просто на практике почти всегда удаеться обойтись одно-направленным)

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


--------------------
user posted image
PM MAIL   Вверх
threef
Дата 26.11.2005, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 375
Регистрация: 27.10.2005
Где: Запорожье

Репутация: 1
Всего: 10



В списке ты хранишь не обьекты, а указатели на них. Освобождаешь память - указатели указывают в никуда, отсюда и ехсепшины. Для освобождения памяти добавь процедурку
Код

FreeAll(CPtrArray &pa)
{
   pa.FreeExtra();
   for(int i=0;i<pa.GetSize();i++)
   {
       delete pa[i];
   }
   pa.RemoveAll();
}

Почистит весь список

Это сообщение отредактировал(а) threef - 26.11.2005, 09:43
PM MAIL   Вверх
AlexPro
Дата 26.11.2005, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 9.11.2005
Где: Санкт-Петербург

Репутация: 3
Всего: 4



Цитата(kometa_triatlon @ 26.11.2005, 00:49)
CVarItem* pItem = new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]);
        m_arrVarList.Add(pItem);

Это зачем? Сделай так:
Код

m_arrVarList.Add(new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]));

и все будет работать
PM MAIL   Вверх
Mad
Дата 26.11.2005, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 2
Всего: 19



AlexPro
Цитата(kometa_triatlon @ 25.11.2005, 23:49)

CVarItem* pItem = new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]);
        m_arrVarList.Add(pItem);

и

Цитата(AlexPro @ 26.11.2005, 11:17)
m_arrVarList.Add(new CVarItem(lpszType, strToken, strSubProgName, iLine, state, m_arrStrCode[iLine]));

в сути одно и тоже, только в первом случае ты сам определяеш локальную переменную класса, а во втором это делает за тебя компилятор smile


--------------------
user posted image
PM MAIL   Вверх
kometa_triatlon
Дата 26.11.2005, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 384
Регистрация: 7.1.2005
Где: Киев

Репутация: 1
Всего: 6



Некоторые не поняли наверное вопроса smile
Мне не нужно удалять список.
Я получил в процессе работы некоторые данные. Теперь хочу добавить их в коллекцию. Я создаю динамически новый объект, загоняю в него данные, потом этот объект добавляю в коллекцию.
Я думал, что сама инфа заносится в коллекцию и я могу удалять объект.
Получается, сам контейнер не хранит информацию, а лишь указывает на нее?
Как мне лучше обойти это?
Создать какой-то дежурный объект моего класса, каждый раз при занесении новой информации изменять данные в нем и потом заносить?
smile


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

--------------
Программирование - самое большое удовольствие, которое вы можете получить, будучи одетым.
PM MAIL ICQ   Вверх
Mad
Дата 26.11.2005, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 2
Всего: 19



Цитата(kometa_triatlon @ 26.11.2005, 15:49)
Теперь хочу добавить их в коллекцию. Я создаю динамически новый объект, загоняю в него данные, потом этот объект добавляю в коллекцию.
Я думал, что сама инфа заносится в коллекцию и я могу удалять объект.

Коллекция (вообщето если точно то контейнер) хранит или указатели на обьекты, или ссылки на одьекты, Самиже обьекты контейнеры не хранят.


Цитата(kometa_triatlon @ 26.11.2005, 15:49)
Как мне лучше обойти это?

А как ты хочеш хранить информацию, и при этом не занимать память ;)
Что-бы минимизировать использование памяти, храни указатели на обьекты класса, хранящии информацию
Можно еще хранить данные не в классе, а в структуре (расход памяти еще снизиться, а контейнеру до лампочки на что указатель)


--------------------
user posted image
PM MAIL   Вверх
kometa_triatlon
Дата 27.11.2005, 03:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 384
Регистрация: 7.1.2005
Где: Киев

Репутация: 1
Всего: 6



Цитата
храни указатели на обьекты класса, хранящии информацию

Я так и делаю)

Интересно, а как же мне тогда освободить память?
После завершения вывода результатов вызвать что-то типа:
Код

FreeAll(CPtrArray &pa)
{
   pa.FreeExtra();
   for(int i=0;i<pa.GetSize();i++)
   {
       delete pa[i];
   }
   pa.RemoveAll();
}

?

Кстати, я пробовал так сделать, но вылетел с exception

Обрисую ситуацию: Есть диалоговое приложение, которое использует функции из DLL.
В библиотеку я передаю строку, обратно получаю указатель на СPtrArray
У меня два таких контейнера: один в классе диалога, другой в классе библиотеки, я сначала заполняю библиотечный, потом возвращаю указатель на него клиенту:
Код

m_arrVarList.Copy( *Run(strCode, m_iLineCount));

Run - функция из dll.
Вот не пойму, как освободить память... Если я уже в самом конце работы после выведения данных из контейнера пытаюсь его (тот, который в классе диалога) удалить в цикле (см. выше) , то вылетаю smile

Добавлено @ 03:07
Есть все-таки MFC-контейнеры, которые хранят информацию, а не указатели? Может быть CObList?


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

--------------
Программирование - самое большое удовольствие, которое вы можете получить, будучи одетым.
PM MAIL ICQ   Вверх
Mad
Дата 27.11.2005, 03:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 2
Всего: 19



Цитата(kometa_triatlon @ 27.11.2005, 02:04)
Есть все-таки MFC-контейнеры, которые хранят информацию, а не указатели? Может быть CObList?

Он хранить только ссылки на обьекты класса.

Цитата(kometa_triatlon @ 27.11.2005, 02:04)
m_arrVarList.Copy( *Run(strCode, m_iLineCount));

есть более простой способ (и использование памяти меньше smile)
Код

// в классе диалога

CSomeDataClass *pData;
int iDataElementsCount;

void FillArray()
{
    iDataElementsCount = Run(strCode, m_iLineCount, &pData);
}

CSomeDataClass* GetDataElement(int index)
{
    return pData[index];
}

void FreeArray()
{
    for(int i=0; i<iDataElementsCount; i++)
        delete pData[i];
    delete pData;
}

// в DLLке

int Run(CString strCode, int m_iLineCount, CSomeDataClass **pArray)
{
    pArray = new char[sizeof(void*)*k]; // k - кол-во возвращяемых элементов

    for() // или while
    {
        ...
        pArray[i] = new CSomeDataClass();
    }
}

Могут быть какието ошибки (писал прямо тут, и компилить не пробывал smile), но общий принцип должен быть понятен.

Кстати сам CPtrArray примерно так и работает, просто в него добавленно еще целаю куча разных ассертов, и возможностей


--------------------
user posted image
PM MAIL   Вверх
threef
Дата 28.11.2005, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 375
Регистрация: 27.10.2005
Где: Запорожье

Репутация: 1
Всего: 10



Обрати внимание именно на

Цитата

int Run(CString strCode, int m_iLineCount, CSomeDataClass **pArray)


**pArray

Если ты хочешь вернуть распределенный массив из функции, то ты должен передавать не массив(*pArray), а ссылку на него(**pArray).

Кроме того, есть шаблонные классы, способные спокойно хранить обьекты а не ссылки на них:
CArray <itemType,itemType>MyArray;
CList <itemType,itemType>MyList;
Только учти, что хранятся КОПИИ обьектов,так что в случае распределения ресурсов в самом обьекте необходимо предусмотреть все в конструкторе копирования. Или храни указатели.

Цитата

Кстати, я пробовал так сделать, но вылетел с exception


Посмотри, что за ехсепшн, где он возникает

Цитата

Можно еще хранить данные не в классе, а в структуре (расход памяти еще снизиться


Не сильно доверяй этому утверждению, расход памяти не зависит от того, структура это или класс. С точки зрения C++ это равнозначно, различия только в доступе по умолчанию.

Это сообщение отредактировал(а) threef - 28.11.2005, 11:21
PM MAIL   Вверх
Neitron
Дата 28.11.2005, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 580
Регистрация: 3.10.2005
Где: Москва

Репутация: нет
Всего: 5



Цитата(Mad @ 26.11.2005, 19:31)
Самиже обьекты контейнеры не хранят.

Расскажи об этом вектору, листу, мапу...
А то они этого не знает, и каждый раз в себя копируют объекты, подлецыsmile((


--------------------
Хороший программист никогда ничего не делает хорошо с первого раза. Он понимает важность патчей.
Ⓘ ⓁⒾⓀⒺ ⓂⓄⓏⒾⓁⓁⒶ
PM MAIL   Вверх
kometa_triatlon
Дата 29.11.2005, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 384
Регистрация: 7.1.2005
Где: Киев

Репутация: 1
Всего: 6



Mad
А что, хороший способ, действительно мог бы и додуматься передавать мой контейнер в функцию из библиотеки, чем копировать...

Neitron
Давно мне, бездельнику, пора бы выучить STL...

threef
Цитата
Не сильно доверяй этому утверждению,

Я и не доверяю smile

ОК, кое-какие идеи появились, будем реализовывать...


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

--------------
Программирование - самое большое удовольствие, которое вы можете получить, будучи одетым.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0542 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.