Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> корректное освобождение памяти, освобождение памяти динамического массив 
V
    Опции темы
Nick007
Дата 17.4.2010, 00:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем доброго времени суток.

у меня есть класс в котором сохраняется массив сообщений  
которы в определенный момент выводит их все разом

Код

class Messg
{
    LPWSTR *ls;
    int cou;
public:
    Messg();
    void MessgShowTest();
    void MessgAdd(LPWSTR ls1);
    void MessgShow();
    int MessgCou();
    LPWSTR MessgMes(int i);
};


В нем есть функция добавления
Код


void Messg::MessgAdd(LPWSTR ls1){
    cou++;
    LPWSTR *ts=new LPWSTR[cou];
    for(int i=0;i<cou-1;i++)
        ts[i]=ls[i];
    ts[cou-1]=ls1;

    if(cou>0)for(int i=0;i<cou;i++){   
    //delete ls[i]; 
        //free(ls[i]);
    }
    //delete []ls;
    ls=ts;
}


во время добавления счетчик увеличивается
после вывода массива сообщений обнуляется

во время выполнения программы (при добавлении сообщений)
происходит увеличение занимаемой программой памяти

после создания нового массива память остается занятой

я пытался некоторыми способами избавиться от этого эффекта
но мои усилия ни к чему не привели

помогите пожайлусто правильно освобождать память
от ставших не нужными сообщений

-------------------

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

скорее всего , что я что то не правильно делал
или не делал
 ------------------
буду очень благодарен всем кто сможет помоч в развязании данной проблемы
PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Nick007, я вообще не понял что ты хотел сказать этой программой. У тебя член класса LPWSTR *ls нигде не используется а в методе MessgAdd происходит выделение памяти для массива, который нигде потом не используется и не уничтожается, естественно происходит утечка памяти.
Ты лучше подробнее расскажи свою задачу. Потому что твой алгоритм никуда не годится.
PM MAIL   Вверх
Nick007
Дата 17.4.2010, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



данный класс накапливает сообщения создаваемые основной программой для их вывода во время вызова определенной функции
вывод в окно производится при помощи функций DirectX
вот  все методы класса:

Код

Messg::Messg()
{cou=0;}

void Messg::MessgAdd(LPWSTR ls1){
    cou++;
    LPWSTR *ts=new LPWSTR[cou];
    for(int i=0;i<cou-1;i++)
        ts[i]=ls[i];
    ts[cou-1]=ls1;

    if(cou>0)for(int i=0;i<cou;i++){   
    //delete ls[i]; 
        //free(ls[i]);
    }
    //delete []ls;
    ls=ts;
}

void Messg::MessgShowTest()
{
    if(cou>0){
    for(int i=0;i<cou;i++)
        MB(ls[i]);//MB(s) это макрос выводящий MessfgeBox
    }
}

void Messg::MessgShow()
{
//текст/*начало
    HFONT hFont;
    LPD3DXFONT pFont = NULL;
    RECT Rec;
    int x1=10;
    int y1=100;
    int x2=1000;
    int y2=700;
    D3DCOLOR MyColor=D3DCOLOR_ARGB(250,250,250,50);
    D3DCOLOR MyColor1=D3DCOLOR_ARGB(250,0,0,0);
    D3DCOLOR MyColor2=D3DCOLOR_ARGB(250,0,250,0);
    // Создаем шрифт
    D3DXCreateFont(g_pD3DDevice,30,10,FW_NORMAL,0,FALSE,1,0,0,DEFAULT_PITCH|FF_MODERN,L"Arial",&pFont);    
    // Координаты прямоугольника
    Rec.left = x1;                            
    Rec.top  = y1;
    Rec.right  = x2;
    Rec.bottom = y2;
    Rec.top  = (10+20*-1)+100;
    pFont->DrawText(NULL,L"текущие сообщения:", -1, &Rec, DT_WORDBREAK, MyColor);
    for(int i=0;i<cou;i++){    
        Rec.left = x1+2;                                     
        Rec.top  = (10+20*(cou-i-1))+100+2;
        pFont->DrawText(NULL,ls[i], -1, &Rec, DT_WORDBREAK, MyColor1);
        Rec.left = x1;                                     
        Rec.top  = (10+20*(cou-i-1))+100;
        pFont->DrawText(NULL,ls[i], -1, &Rec, DT_WORDBREAK, MyColor2);        //MB(ls[i]);    
    }
    // удаляем
    pFont->Release();
    //текст*/конец
    
    cou=0;
}

int Messg::MessgCou(){return cou;}

LPWSTR Messg::MessgMes(int i){return ls[i-1];}



в методе
 void Messg::MessgAdd
(по моему замыслу)
должно происходить
происходит создание нового массива ,заполнение значениями из старого(если они есть)
и замена старого на навый

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

Это сообщение отредактировал(а) Nick007 - 17.4.2010, 00:29
PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 00:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Цитата(Nick007 @  17.4.2010,  00:29 Найти цитируемый пост)
данный класс накапливает сообщения

Каким образом он накапливает? Как я понимаю по вашему замыслу должна прибавляться строка к существующей строке или как? Если так то, есть стандартные функции работы со строками.
Если делать как вы, то по шагам это должно быть так:
1)Создание нового массива с длиной старого + длина новых данных.
2)Копирование данных из старого массива в новый и прибавление новых данных
3)Уничтожение старого массива
Плюс написать в деструкторе освобожение текущего массива, если он непустой.

Добавлено через 2 минуты и 6 секунд
После создания нового массива присвоить соответствующему члену класса значение (указатель) нового массива.
PM MAIL   Вверх
Nick007
Дата 17.4.2010, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



сообщения добовляются при помощи следующего кода:

Код

Messg *m;
int x=20;

    WCHAR *wszOutput=new WCHAR[1024];
    swprintf_s( wszOutput, 1024, L"добавляю значение X=%d ",X);
    m->MessgAdd(wszOutput);  


а выводятся вот так:

Код


    m->MessgShow();

PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Nick007, лучше этот код встроить в функцию MessgAdd, а передавать первым параметром строку-константу, второй X. Меньше геморроя будет с выделением / освобождением памяти.
PM MAIL   Вверх
Nick007
Дата 17.4.2010, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



в функции MessgAdd 
был цикл освобождения массива
привем несколько вариантов
но все не удачные
щас они закоментированы

процесс создания/добавления у меня такой как вы описали
а с уничтожением возникла проблема
над которой я целый день бьюсь

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

Добавлено через 8 минут и 13 секунд
другой вариант ввода:
Код

    m->MessgAdd(L"управление позицией /");


Это сообщение отредактировал(а) Nick007 - 17.4.2010, 00:58
PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Цитата(Nick007 @  17.4.2010,  00:54 Найти цитируемый пост)
процесс создания/добавления у меня такой как вы описали

Прямо такой.
Давайте по моим шагам. Соответствие что я написал и что у вас написано.

Цитата(Nick007 @  17.4.2010,  00:54 Найти цитируемый пост)
а с уничтожением возникла проблема
над которой я целый день бьюсь

Естественно, потому что вы два раза выделяете память и нигде ее не освобождаете.

Но сначала давайте разберемся с выделением памяти. У вас тоже неправильно все сделано.

Кстати я сам затупил.
Щас все объясню.

Это сообщение отредактировал(а) ИванМ - 17.4.2010, 01:04
PM MAIL   Вверх
ИванМ
Дата 17.4.2010, 01:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



К этому коду
Код

WCHAR *wszOutput=new WCHAR[1024];
    swprintf_s( wszOutput, 1024, L"добавляю значение X=%d ",X);
    m->MessgAdd(wszOutput);  

 добавьте
 
Код

delete[] wszOutput.


В методе MessgAdd копируйте полученное значение в новое. Тогда с вышеописанным освобождением памяти мы покончили.
Теперь будем думать что делать с массивом строк.

Тут проблема с тем, что заранее неизвестно количество элементов массива ls.
Это на самом деле глобальная проблема, можно целую теорию развести.
В общем нужно создать сначала массив строк определенной длины. Потом, при переполнении его,создавать новый с большим размером все из него построчно из старого копировать в новое. В стандарте предусмотрено 2 варианта: либо увеличить размер массива в 2 раза, либо 1,5 раз больше исходного.
После выполнения этой операции вы присваиваем члену класса ls значение указателя на полученный массив.
Кроме того, необходимо создать деструктор, который будет построчно удалять все строки этого массива delete[] ls[i] и потом сам массив delete[] ls;
И все, проблема будет решена.



Это сообщение отредактировал(а) ИванМ - 17.4.2010, 01:19
PM MAIL   Вверх
Nick007
Дата 17.4.2010, 01:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Код

MessgAdd(LPWSTR ls1){
    cou++;
//здесь создается новый массив
    LPWSTR *ts=new LPWSTR[cou];
//здесь новый массив заполняется значениями из старого
    for(int i=0;i<cou-1;i++)
        ts[i]=ls[i];
//здесь добавляется новая строка
    ts[cou-1]=ls1;

//в этом цикле я пыеаюсь освобождать отработанный массвив
//но это приводит к ошибке[/color]
    if(cou>0)for(int i=0;i<cou-1;i++){   
//здесь должно уничтожаться содержимое старого массива
    delete ls[i]; 
        //free(ls[i]);
    }
//здесь должен уничтожаться сам массив
    delete []ls;
//здесь ссылке на старый массив присваивается ссылка на новый 
    ls=ts;
}


объясните что я делаю не правильно
PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 01:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Цитата(Nick007 @  17.4.2010,  01:20 Найти цитируемый пост)
ts[i]=ls[i];
//здесь добавляется новая строка
    ts[i]=ls[i];

Здесь ошибка. ts[i] это массив, который нужно копировать, а не присваивать указатель.
Когда вы удалите ls[i], ts[i] тоже удалится и программа сдохнет.
PM MAIL   Вверх
Nick007
Дата 17.4.2010, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



изначально количество элементов равно нулю
при добавление одного сообщения счетчик увеличивается на 1
после вывода сообщений их количество снова равно нулю

Добавлено через 1 минуту и 43 секунды
как правильно скопировать массив
из LPWSTR
?
PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 01:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Nick007, 
Цитата(Nick007 @  17.4.2010,  01:26 Найти цитируемый пост)
изначально количество элементов равно нулю
при добавление одного сообщения счетчик увеличивается на 1

Т.е. вы каждый раз при получении нового сообщения пересоздаете массив с размером больше исходного на 1 элемент. Это не грамотно. Надо его увеличивать на большее число.
Nick007, после вывода сообщений их количество снова равно нулю [/quote]
Значит после вывода сообщений надо тоже удалять весь массив. Но в деструкторе тоже необходимо сделать.

В общем если заменить этот код:
Код

    for(int i=0;i<cou-1;i++)
        ts[i]=ls[i];
//здесь добавляется новая строка
    ts[cou-1]=ls1;


на 

Код

    for(int i=0;i<cou-1;i++)
       wcscpy(ts[i],ls[i]);
//здесь добавляется новая строка
    wcscpy(ts[cou-1],ls1);


то вроде должно работать.

И еще не забудьте добавить 
    
Код

delete[] wszOutput.

после передачи сообщения.

Это сообщение отредактировал(а) ИванМ - 17.4.2010, 01:33
PM MAIL   Вверх
Nick007
Дата 17.4.2010, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Был такой вариант:
Код

strcpy((char*)ts[i],(shar*)ls[i]);

но он работал только если в стеке была только одна строка
при добавлении второй проскакивало исключение
PM MAIL WWW   Вверх
ИванМ
Дата 17.4.2010, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

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



Nick007, 
Цитата(Nick007 @  17.4.2010,  01:32 Найти цитируемый пост)
Был такой вариант:
Выделить всёкод C++
1:
    
strcpy((char*)ts[i],(shar*)ls[i]);

но он работал только если в стеке была только одна строка
при добавлении второй проскакивало исключение 


У вас не char* а wchar_t*. Смотрите как я написал.
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




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


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

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