程序原代码生成步骤:
File->New->Projects->Win32 Application->"HelloWorld"
在WndProc内的WM_COMMAND模块内部设置一断点,程序运行后点击help菜单,程序执行到断点,这时观察堆栈调用信息发现,没有WinMain函数,为什么?
堆栈如下:
WndProc(HWND__ * 0x001c0230, unsigned int 273, unsigned int 104, long 0) line 143
USER32! 77e11d0a()
USER32! 77e11bc8()
USER32! 77e172b4()
WinMainCRTStartup() line 198 + 54 bytes
KERNEL32! 77e9ca90()

解决方案 »

  1.   

    其实这里的WinMainCRTStartup()内部封装了WinMain函数。
    你会在WinMainCRTStartup()函数中看到如下代码:
    ...
    int nRet = _tWinMain(::GetModuleHandle(NULL), NULL, lpszCommandLine,
    (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?
    StartupInfo.wShowWindow : SW_SHOWDEFAULT);
    ...在运行程序时,其实系统并不直接调用我们编写的进入点函数。而调用的是C/C++运行期启动函数。
    这样我们的程序就可以使用运行期函数库的函数。还能确保对象的正确创建于释放。
    更详细的说明请参考<<Windows核心编程>>第4章。
      

  2.   

    函数调用时是都要进行进栈、出栈的。
    在函数调用时,返回地址应该压入堆栈的。
    不过注意的是VC中的"调用堆栈"并不等于"堆栈"。
    调试时可以观察内存堆栈中,在执行到
    USER32! 77e172b4()
    WinMainCRTStartup() line 198 + 54 bytes
    之间已经将WinMain的返回地址压入堆栈中了。而在VC的"调用堆栈"中并没有显示。
    当跟踪到DispatchMessage( &msg )函数返回时,就可以看到WinMain又重新出现。类似的,用"混合模式"跟踪子程序调用(call)时,可以发现,很多情况下进入子程序后
    "调用堆栈"中并不显示父函数的信息。但堆栈中的确已经压入了返回地址。以上.