函数结束后的C ++变量

时间:2012-02-21 14:48:22

标签: c++ winapi variables scope wininet

我有以下代码:

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 ++实践中做到这一点?

4 个答案:

答案 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()函数的任何其他局部变量。

您当前的解决方案更糟糕的是内存泄漏。这不是你在泄漏记忆。事实是该对象不再存在,但您仍然指向该地址。

从我的观点来看,这是未定义的行为。不要这样做。

您可以使用以下选项来解决问题:

  1. 为cpContext变量使用全局变量。
  2. 通过new。
  3. 在堆上分配cpContext
  4. 在另一个上下文中分配cpContext,您确定它将一直存在,直到回调结束。