Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
Мы сами всего творцы!
 Аватар для Alexell
60 / 23 / 1
Регистрация: 06.06.2012
Сообщений: 151
RAD XE4+

Как правильно освободить память в функции?

31.01.2021, 15:01. Показов 2530. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Прошу помощи с правильным удалением и освобождением памяти.
Есть функция, нашел ее на просторах форума. Честно говоря я в этой функции понимаю далеко не все, методом проб и ошибок я все же смог доработать ее под себя и она идеально делает что нужно, за одним исключением - утечки памяти.

При выполнении функции раз в 6 секунд по таймеру, утекает примерно по 30 МБ за минуту и это не останавливается.
Стоит только закомментировать вызов функции //UpdateActions(); как память остается на месте при выполнении остальных действий программы и варьируется лишь на 1-2 МБ, то увеличивается, то уменьшается - в среднем держится на одном значении.


Прошу показать, как и где правильно освободить память в этой функции.
Я пытался удалять и через delete и через Release(), причем в разных местах, но всегда получаю ошибку Access Violation.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void TForm1::UpdateActions()
{
    if(Web->Document)
    {
        TComInterface<IHTMLDocument2> HTMLDoc; //include "Mshtml.h"
        Web->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&HTMLDoc);
        if(HTMLDoc)
        {
            WideString wtext, wcode;
            TComInterface<IHTMLElementCollection> pElements;
            IHTMLElement *pElem = NULL;
            IHTMLElement *ppElem = NULL;
            HTMLDoc->get_all(&pElements);
            long numelems;
            HRESULT hres = pElements->get_length(&numelems);
 
            if (hres == S_OK)
            {
                for (int i=0; i < numelems; i++)
                {
                    VARIANT varIndex;
                    varIndex.vt = VT_UINT;
                    varIndex.lVal = i;
                    VARIANT var2;
                    VariantInit( &var2 );
                    IDispatch* pDisp;
 
                    pElements->item(varIndex, var2, &pDisp);
                    if (SUCCEEDED(pDisp -> QueryInterface (IID_IHTMLElement, (LPVOID*)&pElem)) && pElem)
                    {
                        pElem->get_innerText(&wtext);
                        if (wtext == "Update")
                        {
                            pElem->get_parentElement(&ppElem);
                            ppElem->get_outerHTML(&wcode);
                            if(wcode.Pos("<span class") == 1)
                            {
                                if(!wcode.Pos("button_disabled"))
                                {
                                    pElem->click();
                                    break;
                                }
                            }
                        }
                    }
                }
                //ppElem->Release();
                //pElem->Release();
                //pElements->Release();
                //delete HTMLDoc;
            }
        }
    }
}
Здесь Web - это TCPPWebbrowser, а сама функция ищет на странице кнопку по видимому названию (у нее нету id и name), затем проверяет элемент-родитель и если все соответствует условиям, кликает на кнопку.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
31.01.2021, 15:01
Ответы с готовыми решениями:

Как правильно освободить память
Здрасте! (Тема: Шаблоны функций.) Не могу правильно написать метод для освобождения памяти. В мейне делаю все необходимые мне...

Как правильно освободить память
Есть функция char* md5(const char*). Как освободить память выделенную ею? #include &lt;openssl\md5.h&gt; char* md5(const char* text) { ...

Как правильно освободить память
Написал вот такой костыль: wchar_t* getDate() { time_t seconds = time(NULL); tm timeinfo = *(localtime(&amp;seconds)); return...

4
place status here
 Аватар для gunslinger
3190 / 2227 / 640
Регистрация: 20.07.2013
Сообщений: 6,023
31.01.2021, 18:32
Взял из старого проекта (по твоему вопросу вроде должно быть понятно, что к чему):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 IHTMLDocument2 *pHTMLDocument = NULL;
 if(SUCCEEDED(CppWebBrowser1->Document->QueryInterface(
   IID_IHTMLDocument2, (LPVOID*)&pHTMLDocument)))
   {
   if(pHTMLDocument != NULL)
   {
     IHTMLElementCollection *pAll = NULL;
     if(SUCCEEDED(pHTMLDocument->get_all(&pAll)) && pAll)
     {
       TVariant vName="vb_login_username", vName2="vb_login_password", vName3="cookieuser";
       TVariant vIndex=1;
 
       // login
       IDispatch *pDisp1=NULL;
       if(SUCCEEDED(pAll->item(vName, vIndex, &pDisp1)) && pDisp1)
       {
         IHTMLInputElement *pInput = NULL;
         if(SUCCEEDED(pDisp1->QueryInterface(IID_IHTMLInputElement,
         (LPVOID*)&pInput)) && pInput)
         {
           WideString login = Memo2->Lines->Strings[0];
           if (Trim(login) != "")
           {
             pInput->put_value(login);
             auto_login = 1;  // need to login to continue
           }
           else
             auto_login = 0;  // no need to login further
           pInput->Release();
         }
         pDisp1->Release();
       }
 
       // pass
       IDispatch *pDisp2=NULL;
       if(SUCCEEDED(pAll->item(vName2, vIndex, &pDisp2)) && pDisp2)
       {
         IHTMLInputElement *pInput = NULL;
         if(SUCCEEDED(pDisp2->QueryInterface(IID_IHTMLInputElement,
         (LPVOID*)&pInput)) && pInput)
         {
           WideString pass = RSAPasswordGarena(Memo2->Lines->Strings[1]);
           if (Trim(pass) != "")
           {
             pInput->put_value(pass);
             auto_login = 1;
           }
           else
             auto_login = 0;
           pInput->Release();
         }
         pDisp2->Release();
       }
 
       // save
       IDispatch *pDisp3=NULL;
       if(SUCCEEDED(pAll->item(vName3, vIndex, &pDisp3)) && pDisp3)
       {
         IHTMLInputElement *pInput = NULL;
         if(SUCCEEDED(pDisp3->QueryInterface(IID_IHTMLInputElement,
         (LPVOID*)&pInput)) && pInput)
         {
           pInput->put_checked(1);
           pInput->Release();
         }
         pDisp3->Release();
       }
 
     }
     pAll->Release();
   }
 
    // click SUBMIT()
    IHTMLElementCollection *HTMLForms = NULL;
    if(SUCCEEDED(pHTMLDocument->get_forms(&HTMLForms)) && HTMLForms)
    {
      TVariant vName4(3);
      TVariant vIndex4 = 0;
      IDispatch *pDisp4 = NULL;
      if(SUCCEEDED(HTMLForms->item(vName4, vIndex4, &pDisp4)) && pDisp4)
      {
        IHTMLFormElement *HTMLForm = NULL;
        if(SUCCEEDED(pDisp4->QueryInterface(IID_IHTMLFormElement,
          (LPVOID*)&HTMLForm)) && HTMLForm)
        {
          if (auto_login == 1)
            HTMLForm->submit();
          auto_login = 0;
          HTMLForm->Release();
        }
        pDisp4->Release();
      }
      HTMLForms->Release();
    }
 
   pHTMLDocument->Release();
   }
1
Мы сами всего творцы!
 Аватар для Alexell
60 / 23 / 1
Регистрация: 06.06.2012
Сообщений: 151
31.01.2021, 19:15  [ТС]
gunslinger, Благодарю за ответ. По вашему примеру кое как удалось расставить релизы. К сожалению, у вас нет цикла обхода элементов, это сбивает меня с толку и не дает ответов на всё. Но сейчас релизы стоят и ошибок не выскакивает. Правда утечка осталась, но уменьшилась до 20 МБ/мин. Я не знаю что нужно удалять еще ((

Новый вариант функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
void TForm1::UpdateActions()
{
    if(Web->Document)
    {
        IHTMLDocument2 *HTMLDoc = NULL; //include "Mshtml.h"
        Web->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&HTMLDoc);
        if(HTMLDoc)
        {
            WideString wtext, wcode;
            IHTMLElementCollection *pElements = NULL;
            if(SUCCEEDED(HTMLDoc->get_all(&pElements)) && pElements)
            {
                IHTMLElement *pElem = NULL;
                IHTMLElement *ppElem = NULL;
                IDispatch* pDisp = NULL;
                long numelems;
                HRESULT hres = pElements->get_length(&numelems);
                if (hres == S_OK)
                {
                    for (int i=0; i < numelems; i++)
                    {
                        VARIANT varIndex;
                        varIndex.vt = VT_UINT;
                        varIndex.lVal = i;
                        VARIANT var2;
                        VariantInit( &var2 );
 
                        pElements->item(varIndex, var2, &pDisp);
                        if (SUCCEEDED(pDisp -> QueryInterface (IID_IHTMLElement, (LPVOID*)&pElem)) && pElem)
                        {
                            pElem->get_innerText(&wtext);
                            if (wtext == "Update")
                            {
                                pElem->get_parentElement(&ppElem);
                                ppElem->get_outerHTML(&wcode);
                                ppElem->Release();
                                if(wcode.Pos("<span class") == 1)
                                {
                                    if(!wcode.Pos("button_disabled"))
                                    {
                                        //pElem->click();
                                        break;
                                    }
                                }
                            }
                            pElem->Release();
                        }
                        pDisp->Release();
                    }
                }
            }
            pElements->Release();
        }
        HTMLDoc->Release();
    }
}
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33398 / 21508 / 8236
Регистрация: 22.10.2011
Сообщений: 36,906
Записей в блоге: 12
01.02.2021, 12:58
Лучший ответ Сообщение было отмечено Alexell как решение

Решение

Сделал описание строковых переменных максимально близким к месту использования + поправил обработку ошибок:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void TForm1::UpdateActions()
{
 
    if(Web->Document)
    {
        IHTMLDocument2 *HTMLDoc = NULL; //include "Mshtml.h"
        Web->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&HTMLDoc);
        if(HTMLDoc)
        {
            // WideString wtext, wcode;
            IHTMLElementCollection *pElements = NULL;
            if(SUCCEEDED(HTMLDoc->get_all(&pElements)) && pElements)
            {
                IHTMLElement *pElem = NULL;
                IHTMLElement *ppElem = NULL;
                IDispatch* pDisp = NULL;
                long numelems;
                HRESULT hres = pElements->get_length(&numelems);
                if (hres == S_OK)
                {
                    for (int i=0; i < numelems; i++)
                    {
                        VARIANT varIndex;
                        varIndex.vt = VT_UINT;
                        varIndex.lVal = i;
                        VARIANT var2;
                        VariantInit( &var2 );
 
                        if(SUCCEEDED(pElements->item(varIndex, var2, &pDisp)) && pDisp)
                        {
                        // pElements->item(varIndex, var2, &pDisp);
                        if (SUCCEEDED(pDisp -> QueryInterface (IID_IHTMLElement, (LPVOID*)&pElem)) && pElem)
                        {
                            WideString wtext;
                            pElem->get_innerText(&wtext);
                            if (wtext == "Update")
                            {
                                WideString wcode;
                                pElem->get_parentElement(&ppElem);
                                ppElem->get_outerHTML(&wcode);
                                ppElem->Release();
                                if(wcode.Pos("<span class") == 1)
                                {
                                    if(!wcode.Pos("button_disabled"))
                                    {
                                        //pElem->click();
                                        break;
                                    }
                                }
                            }
                            pElem->Release();
                        }
                        pDisp->Release();
                        }
                    }
                }
            }
            pElements->Release();
        }
        HTMLDoc->Release();
    }
}
Исходных данных, на которых это все тестируется, у меня, разумеется, нет, но проверил на нескольких первых попавшихся - вроде не жрет память (до переноса описания WideString - была небольшая утечка)...
2
Мы сами всего творцы!
 Аватар для Alexell
60 / 23 / 1
Регистрация: 06.06.2012
Сообщений: 151
01.02.2021, 15:09  [ТС]
volvo, я надеялся, что вы поможете, Владимир. Спасибо большое! Протестировал почти 2 часа - утечек действительно нет.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.02.2021, 15:09
Помогаю со студенческими работами здесь

Как правильно освободить память
Здравствуйте все! Подскажите, как правильно освобождать память, выделенную под массив оператором new? int *Arr = new int; ... delete...

Как правильно освободить память деструктором?
Не могу понять, как освободить память деструктором... В общем, я объявляю в private динамический массив на 3 элемента, после чего память от...

Как правильно освободить память в QHash?
Добрый день. Не могу разобраться с парой вопросов. Выделяю память под объект Client, потом этот указатель на объект помещаю в QHash с...

Подскажите пожалуйста, как правильно освободить память
Всем ку! Подскажите пожалуйста, как правильно удалить(освободить память) массива array2D. Array1D&lt;Elem&gt;* array2D = ...

Динамическая матрица. Как правильно освободить память?
int ROWS = NULL; // Объявление переменных для строк и столбцов. int COLS = NULL; cin &gt;&gt; ROWS &gt;&gt; COLS;// Ввод данных cout...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru