这是server error翻译MTTY里ERROR.C的部分代码,非常好的通用错误报告函数:
DWORD ErrorExtender(DWORD dwError, char ** szBuffer)
{
DWORD dwRes = 0;
{
DWORD dwRes = 0;
dwRes = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | 80 ,
NULL, dwError,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPTSTR) szBuffer, 0, NULL);
NULL, dwError,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPTSTR) szBuffer, 0, NULL);
if (dwRes == 0) {
*szBuffer = LocalAlloc(LPTR, 1);
*szBuffer = LocalAlloc(LPTR, 1);
void ErrorReporter(char * szMessage)
{
{
char * szFormat = "Error %d: %s.\n\r%s\r\n"; // format for wsprintf
char * szExtended; // error string translated from error code
char * szFinal; // final string to report
DWORD dwExtSize;
DWORD dwErr;
char * szExtended; // error string translated from error code
char * szFinal; // final string to report
DWORD dwExtSize;
DWORD dwErr;
dwErr = GetLastError();
/*
Get error string from system
*/
dwExtSize = ErrorExtender(dwErr, &szExtended);
/*
allocate buffer for error string from system, passed in string
and extra stuff from the szFormat string
Get error string from system
*/
dwExtSize = ErrorExtender(dwErr, &szExtended);
/*
allocate buffer for error string from system, passed in string
and extra stuff from the szFormat string
*/
szFinal = LocalAlloc(LPTR, strlen(szMessage) + dwExtSize + 30);
szFinal = LocalAlloc(LPTR, strlen(szMessage) + dwExtSize + 30);
if (szFinal == NULL) // if no final buffer, then can't format error
MessageBox(ghwndMain, "Cannot properly report error.", "Fatal Error", MB_OK);
else {
wsprintf(szFinal, szFormat, dwErr, szMessage, szExtended);
MessageBox(ghwndMain, "Cannot properly report error.", "Fatal Error", MB_OK);
else {
wsprintf(szFinal, szFormat, dwErr, szMessage, szExtended);
OutputDebugString(szFinal);
if (DISPLAYERRORS(TTYInfo))
MessageBox(ghwndMain, szFinal, NULL, MB_OK);
MessageBox(ghwndMain, szFinal, NULL, MB_OK);
LocalFree(szFinal); // free final buffer
}
}
/*
free extended string buffer
free extended string buffer
*/
LocalFree(szExtended);
LocalFree(szExtended);
return;
}
return 1;
}
}
return 1;
}
return dwRes;
}
}
一开始看到红字的部分感觉非常奇怪,查了MSDN才明白
lpBuffer
A pointer to a buffer that receives the null-terminated string that specifies the formatted message. If dwFlags includes FORMAT_MESSAGE_ALLOCATE_BUFFER, the function allocates a buffer using the LocalAlloc function, and places the pointer to the buffer at the
address specified in lpBuffer.
This buffer cannot be larger than 64K bytes.
因为使用了FORMAT_MESSAGE_ALLOCATE_BUFFER的FLAG,函数用LocalAlloc申请内存,并把(指向)LocalAlloc申请到的内存(用T代表)的指针(的地址)放到 lpBuffer指定的地址中?我这翻译真不像那么回事。
我的理解是一个指针的内容是另一个指针的地址,很容易就想到指针的指针。上面的代码就好理解了。
我的调试记录:进入函数ErrorReporter后执行 char * szExtended; 这时候 szExtended的地址是0x002df854,值是一个内存地址0xcccccccc,而内存地址0xcccccccc指向的内容是无效的。运行到ErrorExtender内,char ** szBuffer是形参,它的地址是0x002df75c,因为这是一个“指向指针的指针”,所以它的值应该是另一个指针的地址,传递过来的实参确实就是指针szExtended的地址:0x002df854,所以szBuffer的值是0x002df854,这个值是一个内存地址,地址的内容是指针szExtended的内容0xcccccccc。再运行FormatMessage,这时候地址0
x002df854里的内容变成了0x00377fc0, 这是FormatMessage用LocalAlloc申请到的内存的首地址。其实就是改变了szExtended的内容,使它指向了这个内存块。函数返回后szExtended的值就是错误信息字符串的首地址。
我们再来看这句话:and places the pointer to the buffer at the address specified in lpBuffer.,现在可以理解得很清楚了:把指向buffer(错误信息字符串)的pointer放到 lpBuffer.的地址(的内存)中,见如下示意:
指针szBuffer
szExtended的地址0x002df854 --》 指针szExtended
另一个地址0x00377fc0 --》错误信息字符串首地址
|——》错误信息字符串
这就是二次间指,先到szBuffer的地址的值,得到另一个内存地址,再用这个地址得到另一个值。间接访问已经够让人头大了,这个二次间指更让人晕头转向。
坚定“指针的内容是地址”的革命方针,高举“DEBUG”大旗,一切指针问题都是纸老虎。
Skystalker
转裁请注明出处
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论