我有以下代码:
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作为参数回调另一个函数。所以我的问题是,函数结束后doe cpContext会被销毁吗?这会导致内存泄漏,因为无法在函数外部访问cpContext吗?我怎样才能在最佳C ++实践中做到这一点?
答案 0 :(得分:3)
cpContext
在函数结束时被销毁。这会导致未定义的行为,因为在调用回调之前可能会销毁cpContext
。如果从回调中取消引用指向它的指针,则这是未定义的行为。解决此问题的一种方法是避免使用本地范围的变量:
REQUEST_CONTEXT* cpContext = new REQUEST_CONTEXT();
WinHttpSendRequest(request,WINHTTP_NO_ADDITIONAL_HEADERS,0,NULL,NULL,NULL,(DWORD_PTR)cpContext);
请勿在回调函数中忘记delete
。
泄漏将是HINTERNET
句柄,除非你在回调中关闭它。需要使用WinHttpCloseHandle
关闭此句柄,但在异步请求处于活动状态时无法关闭它。
答案 1 :(得分:0)
这取决于REQUEST_CONTEXT
是什么。如果那是一个对象,那么cpContext
就会被破坏。如果它是一个指针,那么指针就会被破坏。
查看你的代码它是一个真实的对象(因为你传递了地址)所以根据你给我们的内容,我会说当SendRequest()
结束时它会被破坏,并且没有内存泄漏
不应该难以测试,对吧?
答案 2 :(得分:0)
与所有局部变量一样,cpContext
确实超出了范围。这不是内存泄漏,而是更糟。该回调将在其生命周期结束后使用一个对象。
如果你100%肯定地知道回调将被精确调用一次,你可以用cpContext
分配new REQUEST_CONTEXT
,并从回调中删除它。如果你不知道,问题就更糟了。您必须使用特定于API的方法来确定对象应该保持多久。
答案 3 :(得分:0)
cpContext在堆栈中被分配为SendRequest()函数的任何其他局部变量。
您当前的解决方案更糟糕的是内存泄漏。这不是你在泄漏记忆。事实是该对象不再存在,但您仍然指向该地址。
从我的观点来看,这是未定义的行为。不要这样做。
您可以使用以下选项来解决问题: