Переменная C ++ после завершения функции - PullRequest
0 голосов
/ 21 февраля 2012

У меня есть следующий код:

void SendRequest(HINTERNET connection, LPCWSTR method, LPCWSTR referer,LPCWSTR path,WINHTTP_STATUS_CALLBACK whCallback){    
    HINTERNET request;
    request=WinHttpOpenRequest( connection, 0,path,0,referer,WINHTTP_DEFAULT_ACCEPT_TYPES,0);
    WinHttpSetStatusCallback(request, (WINHTTP_STATUS_CALLBACK)whCallback,WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,0);
    REQUEST_CONTEXT cpContext;
    WinHttpSendRequest(request,WINHTTP_NO_ADDITIONAL_HEADERS,0,NULL,NULL,NULL,(DWORD_PTR)&cpContext);
};

WinHttpSendRequest не блокируется, поэтому после выполнения функция завершается. Тем не менее, WinHttpSendRequest обратный вызов другой функции с cpContext в качестве параметра. Итак, мой вопрос: уничтожается ли cpContext после завершения функции? Приводит ли это к утечке памяти, так как нет доступа к cpContext вне функции? Как я могу сделать это в лучших практиках C ++?

Ответы [ 4 ]

3 голосов
/ 21 февраля 2012

cpContext уничтожается в конце функции.Это приводит к неопределенному поведению, поскольку cpContext может быть уничтожено до вызова обратного вызова.Если вы разыменуете указатель на него из обратного вызова, это неопределенное поведение.Одним из способов решения этой проблемы было бы избежать использования переменной локальной области видимости:

REQUEST_CONTEXT* cpContext = new REQUEST_CONTEXT();
WinHttpSendRequest(request,WINHTTP_NO_ADDITIONAL_HEADERS,0,NULL,NULL,NULL,(DWORD_PTR)cpContext);

Не забудьте delete это в функции обратного вызова.

Утечка будетHINTERNET обрабатывать, если вы не закрываете его в обратном вызове.Этот дескриптор должен быть закрыт с WinHttpCloseHandle, но вы не можете закрыть его, пока активен асинхронный запрос.

0 голосов
/ 21 февраля 2012

cpContext выделяется в стеке как любая другая локальная переменная вашей функции SendRequest ().

Ваше текущее решение хуже, чем утечка памяти. Дело не в том, что вы теряете память. Дело в том, что объект больше не существует, но вы все еще держите указатель на этот адрес.

С моей точки зрения, это неопределенное поведение. Не делай этого.

У вас есть следующие варианты решения вашей проблемы:

  1. Используйте глобальную переменную для вашей переменной cpContext.
  2. Распределите ваш cpContext в куче через новый.
  3. Выделите cpContext в другом контексте, который, как вы уверены, будет действовать до завершения обратного вызова.
0 голосов
/ 21 февраля 2012

Как и все локальные переменные, cpContext действительно выходит за рамки. Это не утечка памяти, но хуже. Этот обратный вызов будет использовать объект после истечения срока его жизни.

Если вы на 100% уверены, что обратный вызов будет вызван ровно один раз, вы можете выделить cpContext с помощью new REQUEST_CONTEXT и удалить его из обратного вызова. Если вы не знаете, проблема намного хуже. Вы должны будете использовать специфичные для API методы, чтобы выяснить, как долго объект должен оставаться в живых.

0 голосов
/ 21 февраля 2012

Это зависит от того, что REQUEST_CONTEXT.Если это объект, то cpContext уничтожается.Если это указатель, то уничтожается только указатель.

Если смотреть на ваш код, то это фактический объект (потому что вы передаете адрес), поэтому, основываясь на том, что вы нам дали, я бы сказал,уничтожается, когда SendRequest() заканчивается, и нет утечки памяти.

Не должно быть трудно проверить, верно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...