IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]VC++玩转Native Wifi API 3---GOTO在释放资源时的作用

    lincyang发表于 2014-08-08 23:18:01
    love 0

    GOTO语句有着很臭的名声,我们的老师经常教导我们说,不要轻易使用它。

    C++跳转语句有三个:goto、break和continue。它们只是工具,我觉得问题不能归咎于工具,问题在于人。

    就像指针一样,goto这个无条件跳转语句力量还是很强大的,如果滥用,出现问题很难排查。

    但有些时候goto确实是不二选择,例如我遇到的,在函数中有多个出口,而每个出口都遇到释放资源的时候,与其都把释放语句不厌其烦的写一遍,

    不如一个goto语句来的干脆利落。

    下面的例子取自上一篇Native Wifi API文章,由于我们的程序经常控制的wifi的on和off,必须注意释放资源。就拿WlanOpenHandle来说,

    如果不注意对称WlanCloseHandler,程序几次运行后报错:ERROR_REMOTE_SESSION_LIMIT_EXCEEDED

    官网解释为:Too many handles have been issued by the server.

    所以我们会在每个API调用后,确认返回值,如果错误,程序将不再继续向下运行,return之前,我们必须释放资源。当出口很多时,我们要写很多同样的代码,

    很烦躁,难读,代码急速膨胀。但使用goto后,问题便轻松了许多,请看简单例子:

    // ManageWirelessNetwork.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <stdio.h>
    #include <windows.h>
    #include <shellapi.h>
    #include <wlanapi.h>
    
    // Need to link with shell32.lib
    #pragma comment(lib, "shell32.lib")
    #pragma comment(lib, "wlanapi.lib")
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        DWORD dwResult = 0;
        DWORD dwMaxClient = 2;
        DWORD dwCurVersion = 0;
        HANDLE hClient = NULL;
        PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
        PWLAN_INTERFACE_INFO pIfInfo = NULL;
    
        dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);
        if (dwResult != ERROR_SUCCESS) {
            wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
            return false;
        }
    
        dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
        if (dwResult != ERROR_SUCCESS) {
    		wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);
    		goto RELEASE_RESOURCE;
        }
        
        WLAN_PHY_RADIO_STATE state;
        state.dwPhyIndex = 0;
        state.dot11SoftwareRadioState = dot11_radio_state_on;//off here too.
        PVOID pData = &state;
    
        dwResult = WlanSetInterface(hClient,&pIfList->InterfaceInfo[0].InterfaceGuid,
            wlan_intf_opcode_radio_state,sizeof(WLAN_PHY_RADIO_STATE),pData,NULL);
    
        if(dwResult == ERROR_SUCCESS)
        {
            wprintf(L"set state success!\n");
        }
        else
        {
            wprintf(L"set state failed!err is %d\n",dwResult);
        }
    RELEASE_RESOURCE:
    	if(hClient)
    	{
    		WlanCloseHandle(hClient,NULL);
    		hClient = NULL;
    	}
    	if(pIfList)
    	{
    		WlanFreeMemory(pIfList);
    		pIfList = NULL;
    	}
    	if(pIfInfo)
    	{
    		WlanFreeMemory(pIfInfo);
    		pIfInfo = NULL;
    	}
    	return 0;
    }
    

    最后,goto还会用来跳出多重循环。但需要注意的是,只能从内层跳到外层,不可逆操作。



沪ICP备19023445号-2号
友情链接