Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Динамическое выделение памяти, Утечка ?? 
V
    Опции темы
MAXIQ
Дата 25.2.2009, 02:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Здравствуйте, вопрос в следующем есть ли утечка памяти в этом примере? И как ее избежать, если есть,  на Ваш взгляд? (Обработчик Button3Click)

.h
Код

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TLabel *Label1;
        TLabel *Label2;
        TButton *Button1;
        TButton *Button2;
        TLabel *Label3;
        TLabel *Label4;
        TLabel *Label5;
        TButton *Button3;
        TButton *Button4;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall FormDestroy(TObject *Sender);
        void __fastcall Button2Click(TObject *Sender);
        void __fastcall Button4Click(TObject *Sender);
        void __fastcall Button3Click(TObject *Sender);
private:    // User declarations
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


.cpp
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
struct MyStruct
{
 int iN;
 char cStr[256];
};
GLOBALHANDLE hGlobal;
int iSchet=0; //Счетчик элементов массива структур
int iBrowse=0;//Текущий элемент массива структур
MyStruct *p; //Указатель на массив структур
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 if (iSchet==0)
        {
        iSchet++;
        hGlobal=GlobalAlloc(GHND, iSchet*sizeof(MyStruct));
        //if(hGlobal==0)Label3->Caption="Нету памяти на выделение в if";
        p=(MyStruct *)GlobalLock(hGlobal);

        //Заполнение новой структуры (лишь бы заполнить))
        p[0].iN=iSchet;
        itoa(iSchet*10,p[0].cStr,10);
        //---
        Label2->Caption=(int)GlobalSize(p);
        GlobalUnlock(hGlobal);
        Label1->Caption=iSchet;
        }
 else
        {
        iSchet++;
        hGlobal=GlobalReAlloc(hGlobal,sizeof(MyStruct)*iSchet,GHND);
        p=(MyStruct *)GlobalLock(hGlobal);
        //Заполнение
        p[iSchet-1].iN=iSchet;
        itoa((iSchet*10),p[iSchet-1].cStr,10);
        //----
        Label2->Caption=GlobalSize(p);
        GlobalUnlock(hGlobal);
        Label1->Caption=iSchet;
        }
 iBrowse=iSchet;
 Label3->Caption=iSchet;
 }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
GlobalFree(hGlobal);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if(iSchet>0)
{
if(iBrowse>0)
        {
        iBrowse--;
        p=(MyStruct *)GlobalLock(hGlobal);
        //Просмотр назад
        Label4->Caption=p[iBrowse].iN;
        Label5->Caption=p[iBrowse].cStr;
        //----
        GlobalUnlock(hGlobal);
        }
 else
        {
        iBrowse=iSchet-1;
        p=(MyStruct *)GlobalLock(hGlobal);
        //Просмотр
        Label4->Caption=p[iBrowse].iN;
        Label5->Caption=p[iBrowse].cStr;
        //----
        GlobalUnlock(hGlobal);
        }
 Label3->Caption=iSchet;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
if(iSchet>0)
{
if(iBrowse<iSchet-1)
        {
        iBrowse++;
        p=(MyStruct *)GlobalLock(hGlobal);
        //Просмотр вперед
        Label4->Caption=p[iBrowse].iN;
        Label5->Caption=p[iBrowse].cStr;
        //----
        GlobalUnlock(hGlobal);
        }
else
        {
        iBrowse=0;
        p=(MyStruct *)GlobalLock(hGlobal);
        //----
        Label4->Caption=p[iBrowse].iN;
        Label5->Caption=p[iBrowse].cStr;
        //----
        GlobalUnlock(hGlobal);
        }
Label3->Caption=iSchet;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
p=(MyStruct *)GlobalLock(hGlobal);
for(int i=iBrowse;i<iSchet;i++)
        {
        //Удаление
         if (i<iSchet-1)p[i]=p[i+1];//Вот эта строка мне покоя не дает
        //Что происходит с той областью на которое указывал p[i]? Утечки памяти нет?
        //или он так и будет болтаться в куче до перезагрузки? И надо копировать
        //структуры поэлементно?
        }
if(iSchet>1)
        {
        iSchet--;
        iBrowse--;
        if (iBrowse<0)iBrowse=iSchet-1;
        Label4->Caption=p[iBrowse].iN;
        Label5->Caption=p[iBrowse].cStr;
        hGlobal=GlobalReAlloc(hGlobal,sizeof(MyStruct)*(iSchet),GHND);
        }
GlobalUnlock(hGlobal);
Label3->Caption=iSchet;
}
//---------------------------------------------------------------------------

PM MAIL   Вверх
Artemon
Дата 26.2.2009, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а ты мне нравишься
***


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

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



Указатель на пямять, хранящийся в элементе массива p[i] - остается в памяти до выхода из программы.

Чтобы отслеживать подобные ситуации поставь в свойствах проекта галочку Code Guard и он тебе покажет где у тебя не освобождается память.


--------------------
Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru
PM MAIL   Вверх
MAXIQ
Дата 26.2.2009, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Хороший знак, Code Guard молчит, возмущается только после того, как я создал объект через new и не удалил его спецом)). Однако, чтоб снять у меня все сомнения может кто сказать что с блоком памяти на который указывал p[i] происходит, указатель на него, хранившийся ранее переписан на следующий, то есть обратиться уже нельзя, но блок то вроде остался?  Или он будет заполнен если системе понадобится память так как память перемещаемая (флаг HGND)??
PM MAIL   Вверх
Artemon
Дата 26.2.2009, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а ты мне нравишься
***


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

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



Конечно останется, получится блок потерянной памяти.

Это сообщение отредактировал(а) Artemon - 26.2.2009, 18:38


--------------------
Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru
PM MAIL   Вверх
Vyacheslav
Дата 26.2.2009, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

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



У Вас указатель один. Выделенныя память предстваляет массив байтов размером  sizeof(MyStruct)*iSchet
Вот это 
Код

p[i]=p[i+1]

будет просто означать побитное копирование одной стркутуры в другую.
Память в данном случе не теряется. 
Вопрос в другом. Нафига такие сложности и переход от С++ к С?
Почему просто нельзя было решить этот вопрос с помощью new?


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Artemon
Дата 27.2.2009, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а ты мне нравишься
***


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

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



Да действительно память выделяется сразу целому блоку, но меня смутила переменная iSchet, при уменьшении которой мы просто не сможем узнать начальный размер массива.
Но опятьже упустил из внимания тот факт, что при уменьшении iSchet - мы перераспределяем память.


--------------------
Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru
PM MAIL   Вверх
MAXIQ
Дата 27.2.2009, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Нафига:
1. Структур может быть много.
2. Структуры довольно большие (в коде просто пример, дабы не загружать лишним)
3. Для учебных целей)))

На основании выше сказанного память решил делать перемещаемую.

Спасибо всем, очень помогли.

P.S. Вячеслав, а пример с new, чтоб были реализованы добавление, просмотр, удаление можешь сделать? Тогда тему можно считать полностью исчерпаной и мечу вопрос как решенный.
PM MAIL   Вверх
math64
Дата 27.2.2009, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

// Выделение памяти в первый раз (в конструкторе)
p = new MyStruct[iSchet]; // или p = NULL;
...
// Увеличение объёма памяти
MyStruct* oldP = p;
int oldSchet = iSchet;
iSchet++;
p = new MyStruct[iSchet];
memset(p, 0, sizeof(MyStruct)*iSchet);
if (oldP != NULL) {
  memcpy(p, oldP, sizeof(MyStruct)*oldSchet);
  delete oldP;
}
...
// Удаление - в деструкторе
delete p;

PM   Вверх
MAXIQ
Дата 28.2.2009, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ОК. Спасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

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

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

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

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


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

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


 




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


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

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