Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2311844
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类: WINDOWS

2007-05-06 00:32:43

已有无数的书籍和网上的文章探讨过这个问题, 然而, 多数停留在这里:
CMyApp theApp;

theApp 是一个C++的全局对象, 因此会先于main函数运行.
_tWinMain 定义在 appmodul.cpp 中(不是少写了e, 微软为保证8.3文件名故意为之). 至此为止好像就皆大欢喜了.

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow)
{
    // call shared/exported WinMain
    return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

_tWinMain是一个宏, 视是否设置UNICODE宏而被替换为 wWinMain或WinMain

问题来了, 东西是找到了, 可是它怎么成为你的项目的一部分的? 毕竟appmodul.cpp 是藏在VC安装目录下的MFC源码(微软只提供MFC的部分源码)中, 难道是编译环境自动在编译时"插入"了这个源文件? 在网上搜索时的确找到这样想当然的说法, 编译环境不会这么做!

验证办法是: 生成一个MFC项目, build, 然后查看output窗口, 点击那个build的日志文件, 里面会有build过程的详细记录, 把这个记录中的命令COPY出来, 另存为一个.bat 文件, 运行这个.bat文件来生成最终的程序, 从这里你可以扔掉VC开发环境, 使得它不可能神秘地做一些你不知道的事情, 但是, 仅仅通过命令行来编译链接同样可以得到最终的可执行程序, 这说明并不是VC编译器所谓插入了对 appmodul.cpp的编译. 通过对每个命令的分析, cl和link命令行上也没有"神秘"的选项显示额外链接了什么文件.

那么appmodul.cpp的编译结果完全可以是预编译好的库被链接到最终可执行文件中的, 这个动作只能发生在link阶段, 那么link命令上又没有? 怎么回事?

原来是在afx.h 文件中, 通过#pragma comment(lib, "lib文件.lib")
这样的编译器扩展指示符实现的. 根据是否是UNICODE版本, 是否是DEBUG版本, 链入不同的静态MFC库文件, 其中u代表UNICODE, d代表DEBUG:
mfcs71u.lib
mfcs71.lib
mfcs71ud.lib
mfcs71d.lib
用strings (unix下的小程序, 可以通过cygwin或gnu win32这样的项目得到)或lib命令可以看到这些.
lib /LIST ..\atlmfc\lib\mfcs71.lib

Microsoft (R) Library Manager Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

INTEL\$DLL.W\stdafx.obj
INTEL\$DLL.W\nolib.obj
INTEL\$DLL.W\appmodul.obj
INTEL\$DLL.W\dllmodul.obj
INTEL\$DLL.W\oleexp.obj
INTEL\$DLL.W\dumpstak.obj
INTEL\$DLL.W\sockexp.obj

可以看到其中就有 appmodul.obj

lib mfcs71.lib /extract:INTEL\$DLL.W\appmodul.obj /out:tmp.obj
可以把它抽取出来. 再用反汇编工具分析, 因为这个函数只有一句话, 就是调用AfxWinMain函数, 所以用objdump反汇编的结果也很简单, 直接的一个跳转. 因为AfxWinMain是在dll中动态实现.

阅读(2108) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~