这种代码结构如何组织?goto or do…while(0)? (一)

2014-11-24 12:03:42 · 作者: · 浏览: 1

灰常感谢各位达人昨天的热心回帖,让我受益匪浅。我仰望夜空,群星点点,就如各位的点睛之语,在无尽的苍穹闪耀。这让我深深地意识到,在这里,不仅可以分享成果,也可以分享困惑、分享寂寞。(开场白到此结束~)
在平常的编程中,我发现很容易遇到这种结构:
(1号方案)
BOOL foo()
{
BOOL bRet = FALSE;

HANDLE hProcess = OpenProcess(...);

if (hProcess != NULL)
{
HANDLE hToken = OpenProcessToken(hProcess, ...);

if (hToken != NULL)
{
// ...

if (LookupPrivilegeva lue(...))
{
if (AdjustTokenPrivileges(hToken, ...))
{
bRet = TRUE;
}
}

CloseHandle(hToken);
}

CloseHandle(hProcess);
}

return bRet;
}
如上写法,容易造成缩进级别不断增加。为了避免这种情况,可以改成:
(2号方案)
BOOL foo()
{
HANDLE hProcess = OpenProcess(...);

if (hProcess == NULL)
{
return FALSE;
}

HANDLE hToken = OpenProcessToken(hProcess, ...);

if (hToken == NULL)
{
CloseHandle(hProcess);

return FALSE;
}

// ...

if (!LookupPrivilegeva lue(...))
{
CloseHandle(hToken);
CloseHandle(hProcess);

return FALSE;
}

if (!AdjustTokenPrivileges(hToken, ...))
{
CloseHandle(hToken);
CloseHandle(hProcess);

return FALSE;
}

CloseHandle(hToken);
CloseHandle(hProcess);

return TRUE;
}
这样,又引来了新的问题,每次 return FALSE 时的清理任务比较麻烦,要是每步操作都引进新的 HANDLE 的话,后续的清理工作就变得非常繁重。有人推荐do…while(0)的结构,有人推荐goto。这两种形式分别是——
do…while(0):
(3号方案)
BOOL foo()
{
HANDLE hProcess = OpenProcess(...);

if (hProcess == NULL)
{
return FALSE;
}

BOOL bRet = FALSE;

do
{
HANDLE hToken = OpenProcessToken(hProcess, ...);

if (hToken == NULL)
{
break;
}

// ...

BOOL bRetInner = FALSE;

do
{
if (!LookupPrivilegeva lue(...))
{
break;
}

if (!AdjustTokenPrivileges(hToken, ...))
{
break;
}

bRetInner = TRUE;

} while (0);

CloseHandle(hToken);

if (!bRetInner)
{
break;
}

bRet = TRUE;

} while (0);

CloseHandle(hProcess);

return bRet;
}
这种结构可以避免每次 return FALSE 前的一堆清理工作,但缺点是,有几个依赖性的 HANDLE,就要嵌套几层的 do…while(0),有时候也会遇到需要三四层嵌套的情形。
goto:
(4.1号方案)

BOOL foo()
{
BOOL bRet = FALSE;

HANDLE hProcess = OpenProcess(...);

if (hProcess == NULL)
{
goto CLEAR;
}

HANDLE hToken = OpenProcessToken(hProcess, ...);

if (hToken == NULL)
{
goto CLEAR;
}

// ...

if (!LookupPrivilegeva lue(...))
{
goto CLEAR;
}

if (!AdjustTokenPrivileges(hToken, ...))
{
goto CLEAR;
}

bRet = TRUE;

CLEAR:
if (hToken != NULL)
{
CloseHandle(hToken);
}

if (hProcess != NULL)
{
CloseHandle(hProcess);
}

return bRet;
} (4.2号方案)

BOOL foo()
{
BOOL bRet = FALSE;

HANDLE hProcess = OpenProcess(...);

if (hProcess == NULL)
{
goto ERROR_LEVEL0;
}

HANDLE hToken = OpenProcessToken(hProcess, ...);

if (hToken == NULL)
{
goto ERROR_LEVEL1;
}

// ...

if (!LookupPrivilegeva lue(...))
{
goto ERROR_LEVEL2;
}

if (!AdjustTokenPrivileges(hToken, ...))
{
goto ERROR_LEVEL2;
}

bRet = TRUE;

ERROR_LEVEL2:
CloseHandle(hToken);
ERROR_LEVEL1:
CloseHan