Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/14: Рейтинг темы: голосов - 14, средняя оценка - 4.79
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
1

Освобождение памяти в многопоточной функции

19.10.2019, 20:52. Показов 2895. Ответов 20

Author24 — интернет-сервис помощи студентам
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
void DispThreadsNT::SetCallDZ (MESDZ* pMesDZ,     
                               LPVOID pData,     
                               int nLenData,     
                               DWORD dwPause)     
{
    MESCALL MesCall;
    
    CopyMemory (&(MesCall.MesDZ), pMesDZ, sizeof (MESDZ));
    MesCall.nLenData = 0;
    MesCall.pData = NULL;
 
    MesCall.dwPause = dwPause;
    
    
    if (nLenData != 0 && pData != NULL)
    {
       
        MesCall.pData = new BYTE [nLenData];
        
        if (MesCall.pData != NULL)
        {
            
            CopyMemory (MesCall.pData, pData, nLenData);
            MesCall.nLenData = nLenData;
        }
        else
            MesCall.pData = NULL;
    }
    
    
    MESCALL* pMesCallData = new MESCALL;
    if (pMesCallData)
 
 
        CopyMemory (pMesCallData, &MesCall, sizeof(MESCALL));
 
    
   if (pMesDZ->wParam == 0xFFFF)
       QApplication::sendEvent(this, new UserEvent(MES_CALL_DZ,0,(LPARAM)pMesCallData));
   else
       postEvent(this, new UserEvent(MES_CALL_DZ,0,(LPARAM)pMesCallData));
 
}
 
Помогите, пожалуйста, начинающему программисту. При работе функции не освобождается память, приложение ест оперативку. 
 
Объект MesCall.pData создается, но не удаляется. Не соображу как правильно его удалить, чтобы многотопочность не пострадала.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.10.2019, 20:52
Ответы с готовыми решениями:

Указатели. Освобождение памяти в функции
Здравствуйте, разбираю учебный код, к сожалению, нет к нему комментария на нужный мне вопрос: В...

Как правильно записать в виде функции выделение памяти для двумерного массива и ее освобождение
Здравствуйте! Подскажите, как правильно записать в виде функции выделение памяти для двумерного...

Резервирование памяти/освобождение памяти для трехмерного массива
Необходимо создать трехмерный массив (A), в котором элементы вдоль направления Z выли бы выровнены...

Освобождение памяти в отдельной функции
#include<stdio.h> #include<stdlib.h> void delmem(int ***a,int **q,int **s,int n); void main()...

20
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
19.10.2019, 21:11 2
tanya1179, освобождать память в вашем случае должен тот, кто UserEvent получает.
Если эти данные только читаются получателем (в смысле не он не принимает владение ими), то можно освобождение сделать в деструкторе UserEvent.
1
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
19.10.2019, 21:29  [ТС] 3
UserEvent определен вот так:

C++
1
2
3
4
5
6
7
8
9
10
class UserEvent : public QCustomEvent
{
public:
    UserEvent(UINT Msg, WPARAM wP, LPARAM lP);
    WPARAM GetWParam() {return wParam;}
    LPARAM GetLParam() {return lParam;}
private:
    WPARAM wParam;
     LPARAM lParam;
};
Подскажите как написать деструктор для удаления вышеописанного объекта
0
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
19.10.2019, 22:21 4
tanya1179, Лучше сделать как-то так:
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
class UserMesCallEvent : public UserEvent 
{
public:
    UserMesCallEvent(UINT Msg, WPARAM wP, std::unique_ptr<MESCALL> && lP) 
        : UserEvent(Msg, wP, (LPARAM)lP.get()), lParam(std::move(lP))
    { }
 
private:
    std::unique_ptr<MESCALL> lParam;
};
 
...............
 
 
void DispThreadsNT::SetCallDZ (MESDZ* pMesDZ,     
                               LPVOID pData,     
                               int nLenData,     
                               DWORD dwPause)     
{
    std::unique_ptr<MESCALL> pMesCall(new(std::nothrow) MESCALL);
    if(pMesCall)
    {
        CopyMemory(&pMesCall->MesDZ, pMesDZ, sizeof(MESDZ));
        pMesCall->nLenData = 0;
        pMesCall->pData = NULL;
 
        pMesCall->dwPause = dwPause;
       
        if(nLenData != 0 && pData != NULL)
        {
            pMesCall->pData = new(std::nothrow) BYTE[nLenData];
            if(pMesCall->pData)
            {
                CopyMemory(pMesCall->pData, pData, nLenData);
                pMesCall->nLenData = nLenData;
            }
        }
    }
    if(pMesDZ->wParam == 0xFFFF)
        QApplication::sendEvent(this, new UserMesCallEvent(MES_CALL_DZ, 0, std::move(pMesCall));
    else
        postEvent(this, new UserMesCallEvent(MES_CALL_DZ, 0, std::move(pMesCall)));
}
Добавлено через 4 минуты
У MESCALL тоже нужен деструктор, чтобы почистить pData.
Если MESCALL - это сторонняя сишная структура, которую нельзя менять, то вопрос можно решить написав правильный deleter для unique_ptr (который перед удалением самого объекта MESCALL, сначала проверит и освободит буфер pData).
1
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
19.10.2019, 22:32  [ТС] 5
Цитата Сообщение от DrOffset Посмотреть сообщение
Если MESCALL - это сторонняя сишная структура, которую нельзя менять, то вопрос можно решить написав правильный deleter для unique_ptr
Структура MESCALL вот такая:

C++
1
2
3
4
5
6
7
struct MESCALL
{
    MESDZ       MesDZ;              
    LPVOID      pData;           
    int      nLenData;            
    DWORD     dwPause;           
};
Понимаю, что выгляжу совсем неопытной(это так и есть), но помогите с последним шагом, пожалуйста.
0
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
19.10.2019, 22:36 6
Лучший ответ Сообщение было отмечено tanya1179 как решение

Решение

Цитата Сообщение от tanya1179 Посмотреть сообщение
помогите с последним шагом, пожалуйста.
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
struct MESCALLDeleter
{
    void operator()(MESCALL * ptr)
    {
        delete[] (BYTE*)ptr->pData;
        delete ptr;
    }
};
 
typedef std::unique_ptr<MESCALL, MESCALLDeleter> PMESCALL;
 
class UserMesCallEvent : public UserEvent 
{
public:
    UserMesCallEvent(UINT Msg, WPARAM wP, PMESCALL && lP) 
        : UserEvent(Msg, wP, lP.get()), lParam(std::move(lP))
    { }
    
private:
    PMESCALL lParam;
};
 
...............
 
void DispThreadsNT::SetCallDZ (MESDZ* pMesDZ,     
                               LPVOID pData,     
                               int nLenData,     
                               DWORD dwPause)     
{
    PMESCALL pMesCall( new(std::nothrow) MESCALL );
    if(pMesCall)
    {
        CopyMemory (&pMesCall->MesDZ, pMesDZ, sizeof(MESDZ));
        pMesCall->nLenData = 0;
        pMesCall->pData = NULL;
 
        pMesCall->dwPause = dwPause;
       
        if(nLenData != 0 && pData != NULL)
        {
            pMesCall->pData = new(std::nothrow) BYTE[nLenData];
            if(pMesCall->pData)
            {
                CopyMemory(pMesCall->pData, pData, nLenData);
                pMesCall->nLenData = nLenData;
            }
        }
    }
    if(pMesDZ->wParam == 0xFFFF)
        QApplication::sendEvent(this, new UserMesCallEvent(MES_CALL_DZ, 0, std::move(pMesCall));
    else
        postEvent(this, new UserMesCallEvent(MES_CALL_DZ, 0, std::move(pMesCall)));
}
1
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
19.10.2019, 22:41  [ТС] 7
Спасибо огромное! Это просто исчерпывающе!
0
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
19.10.2019, 22:43 8
tanya1179, для unique_ptr на забудьте #include <memory>.

Некоторое замечание по этому коду: у вас может все сломаться, если вы попытаетесь передавать LPARAM от полученного Event`а (в месте обработки) куда-то, где он будет использоваться дольше, чем живет объект события. Учитывайте это. Мне отсюда может быть не видно всех деталей.
1
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
20.10.2019, 00:13  [ТС] 9
Спасибо, учту обязательно. Код достался мне в наследство, еще в нем разбираюсь)
..
0
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
21.10.2019, 13:44  [ТС] 10
Попробовала это решение, но есть одно но! Я не могу использовать с++11, поэтому unique_ptr мне не доступен, к сожалению.
Помогите найти решение без него.
0
фрилансер
5498 / 5094 / 1047
Регистрация: 11.10.2019
Сообщений: 13,341
21.10.2019, 13:48 11
tanya1179, IDE какая ?
0
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
21.10.2019, 14:03  [ТС] 12
gcc 3.4.3, qt-3.3
0
фрилансер
5498 / 5094 / 1047
Регистрация: 11.10.2019
Сообщений: 13,341
21.10.2019, 14:07 13
tanya1179, а чего Qt такая древняя? В Qt есть класс QSharedPointer , но я не знаю, когда его ввели

udp - Этот класс был введён в Qt 4.5.
0
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
21.10.2019, 14:08 14
C++
1
2
3
4
   if (pMesDZ->wParam == 0xFFFF)
       QApplication::sendEvent(this, new UserEvent(MES_CALL_DZ,0,(LPARAM)pMesCallData));
   else
       postEvent(this, new UserEvent(MES_CALL_DZ,0,(LPARAM)pMesCallData));
У вас тут сложная конструкция отправки сообщения. Сообщение может быть отправлено синхронно или асинхронно в зависимости от значения wParam. Если верить документации Qt, то для синхронного вызова (send) уничтожение объекта возлагается на вызывающую сторону, а для асинхронного (post) уничтожением объекта займётся сам Qt.
0
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
21.10.2019, 14:11  [ТС] 15
В qt-3.3 нет QSharedPointer еще, он только в 4-ой появился
0
фрилансер
5498 / 5094 / 1047
Регистрация: 11.10.2019
Сообщений: 13,341
21.10.2019, 14:13 16
tanya1179, а вот ещё вопрос. Я так понял, ты в пределах одного приложения отправляешь сообщение, содержащее экземпляр типа MESCALL. Может, стОит заменить на глобальную очередь (синхронизированную, если многопоточка).
0
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
21.10.2019, 14:17  [ТС] 17
Приложение писала не я, оптимизировать пытаюсь, можно попробовать в синхронизированную очередь все сложить, посмотреть , не будет ли тормозить...
0
фрилансер
5498 / 5094 / 1047
Регистрация: 11.10.2019
Сообщений: 13,341
21.10.2019, 14:19 18
tanya1179, тормозить там нечему. Принимающая сторона в таймере (интервал зависит от задач) или в своём потоке вытаскивает сообщения и обрабатывает
0
0 / 0 / 0
Регистрация: 03.09.2015
Сообщений: 11
21.10.2019, 14:23  [ТС] 19
Спасибо, попробую
0
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
21.10.2019, 18:38 20
Лучший ответ Сообщение было отмечено tanya1179 как решение

Решение

Цитата Сообщение от tanya1179 Посмотреть сообщение
Попробовала это решение, но есть одно но! Я не могу использовать с++11, поэтому unique_ptr мне не доступен, к сожалению.
Помогите найти решение без него.
Такие важные вещи стоит сразу указывать.
Вот код для С++03.
Кликните здесь для просмотра всего текста
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
class UserMesCallEvent : public UserEvent 
{
public:
    UserMesCallEvent(UINT Msg, WPARAM wP, std::auto_ptr<MESCALL> lP) 
        : UserEvent(Msg, wP, lP.get()), lParam(lP)
    { }
    ~UserMesCallEvent()
    {
        if(lParam.get())
        {
            delete[] (BYTE *)lParam->pData;
        }
    }
    
private:
    std::auto_ptr<MESCALL> lParam;
};
 
...............
 
void DispThreadsNT::SetCallDZ (MESDZ* pMesDZ,     
                               LPVOID pData,     
                               int nLenData,     
                               DWORD dwPause)     
{
    std::auto_ptr<MESCALL> pMesCall( new(std::nothrow) MESCALL );
    if(pMesCall.get())
    {
        CopyMemory (&pMesCall->MesDZ, pMesDZ, sizeof(MESDZ));
        pMesCall->nLenData = 0;
        pMesCall->pData = NULL;
 
        pMesCall->dwPause = dwPause;
       
        if(nLenData != 0 && pData != NULL)
        {
            pMesCall->pData = new(std::nothrow) BYTE[nLenData];
            if(pMesCall->pData)
            {
                CopyMemory(pMesCall->pData, pData, nLenData);
                pMesCall->nLenData = nLenData;
            }
        }
    }
    if(pMesDZ->wParam == 0xFFFF)
        QApplication::sendEvent(this, new UserMesCallEvent(MES_CALL_DZ, 0, pMesCall);
    else
        postEvent(this, new UserMesCallEvent(MES_CALL_DZ, 0, pMesCall));
}
1
21.10.2019, 18:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.10.2019, 18:38
Помогаю со студенческими работами здесь

Освобождение памяти, выделенной под переменную во внутренней функции
Подскажите, какая команда служит для освобождения памяти, заданной под переменную в matlab во...

Освобождение памяти
Подскажите, пожалуйста, я ещё зелёный в C#. Есть у меня класс Form1, при определённом событии в нём...

Освобождение памяти
Собственно есть простенький класс class Human { public: Human ( ); void...

Освобождение памяти
Есть класс, в котором я выделяю память с помощью new. В деструкторе класса я с помощью delete...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru