第二人生的源码分析 3 程序入口点

所有Windows图形应用程序都是拥有相同的入口点函数WinMain,因此第二人生的程序也不例外。下面先来看看这个函数的代码,如下:

//蔡军生 2007/12/28 QQ:9073204 深圳

#001 int APIENTRY WinMain(HINSTANCE hInstance,

#002                       HINSTANCE hPrevInstance,

#003                       LPSTR     lpCmdLine,

#004                       int       nCmdShow)

#005 {

#006  LLMemType mt1(LLMemType::MTYPE_STARTUP);

这行代码主要作用就是声明跟踪内存分配的类型。LLMemType类统计当前使用内存大小,并且可以输出内存的类型信息。

#007

#008  // *FIX: global

#009  gIconResource = MAKEINTRESOURCE(IDI_LL_ICON);

这行代码主要获取资源里的ICON图标句柄。

#010

#011  // In Win32, we need to generate argc and argv ourselves...

#012  // Note: GetCommandLine() returns a potentially return a LPTSTR

#013  // which can resolve to a LPWSTR (unicode string).

#014  // (That‘s why it‘s different from lpCmdLine which is a LPSTR.)

#015  // We don‘t currently do unicode, so call the non-unicode version

#016  // directly.

#017  LPSTR cmd_line_including_exe_name = GetCommandLineA();

这里是获取命令行参数,在Windows API一日一练里已经介绍过,如果不懂可以参考它。

#018

#019  const S32 MAX_ARGS = 100;

#020  int argc = 0;

#021  char* argv[MAX_ARGS];          /* Flawfinder: ignore */

#022

#023  fill_args(argc, argv, MAX_ARGS, cmd_line_including_exe_name);

上面这段代码是分析输入的命令行参数。

#024

#025  LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32();

这行代码开始创建Windows窗口管理程序,也就是第二人生的管理类。

#026

#027  // *FIX:Mani This method is poorly named, since the exception

#028  // is now handled by LLApp.

#029  bool ok = LLWinDebug::setupExceptionHandler();

这行代码实现了加载dbghelp.dll的功能,主要为了生成程序运行出错信息报表,可以精确地定位在那个模块里出错,并且把当时的环境参数全部生成报表,上传给第二人生开发厂家,以便改正这个出错的原因。

#030

#031  // Actually here‘s the exception setup.

#032  LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;

#033  prev_filter = SetUnhandledExceptionFilter(viewer_windows_exception_handler);

这里设置了系统异常出错处理函数,当应用程序产生非法出错时,就会调用这个函数来生成报表。

#034  if (!prev_filter)

#035  {

#036         llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl;

#037         ok = FALSE;

#038  }

#039  if (prev_filter != LLWinDebug::handleException)

#040  {

#041         llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl;

#042         ok = FALSE;

#043   }

上面这段代码主要判断是否设置Windows异常处理成功。

#044

#045  viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);

这行代码保存异常处理函数。

#046

#047  ok = viewer_app_ptr->tempStoreCommandOptions(argc, argv);

#048  if(!ok)

#049  {

#050         llwarns << "Unable to parse command line." << llendl;

#051         return -1;

#052  }

#053

上面保存命令行参数。

#054  ok = viewer_app_ptr->init();

#055  if(!ok)

#056  {

#057         llwarns << "Application init failed." << llendl;

#058         return -1;

#059  }

#060

调用函数init来初始化整个应用程序,比如创建线程,初始化OpenGL等等,在这个函数里实现大部份功能的初始化。

#061         // Run the application main loop

#062  if(!LLApp::isQuitting())

#063  {

#064         viewer_app_ptr->mainLoop();

#065  }

上面第62行检查否有退出应用程序的可能。

第64行就进入了Windows应用程序的消息处理函数,在这个函数里实现主窗口的消息处理,还实现空闲处理,键盘输入处理,接收到网络命令,以及OpenGL渲染。

#066

#067  if (!LLApp::isError())

#068  {

#069         //

#070         // We don‘t want to do cleanup here if the error handler got called -

#071         // the assumption is that the error handler is responsible for doing

#072         // app cleanup if there was a problem.

#073         //

#074         viewer_app_ptr->cleanup();

#075  }

#076  delete viewer_app_ptr;

#077  viewer_app_ptr = NULL;

#078  return 0;

#079 }

上面这段代码,检查是否出错退出,如果出错就清空所有分配的资源。最后删除应用程序管理类。

通过这个函数的学习,会发现第二人生的代码写得比较强悍的,不但出错的处理面面具到,还具备了运行时调试信息输出,强大的LOG系统功能。通过这个函数应学会怎么样添加处理系统异常出错的方法,调试发行版的程序方法,怎么生成具体的报表发送给软件开发厂商的实现。

总结一下,这里运行的流程:

1、             调用WIN API函数GetCommandLineA来获取命令行参数。

2、             调用fill_args函数分析命令行参数。

3、             调用函数LLWinDebug::setupExceptionHandler来加载调试库DebugHlp.dll。

4、             调用函数SetUnhandledExceptionFilter来设置新异常处理。

5、             调函数viewer_app_ptr->init来实始化管理类所有初始化工作。

6、             调用函数viewer_app_ptr->mainLoop进入Windows的消息循环处理。

7、             删除所有分配的资源。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/skiwnchh/p/10347668.html

时间: 2024-08-30 06:31:55

第二人生的源码分析 3 程序入口点的相关文章

腾讯精选面试重点问题:Android源码分析--应用程序启动

面试官:什么是应用程序启动 应用程序的启动,又可称为根Activity的启动.但是在讲应用程序启动之前,我们有必要对应用程序进程(AppProcess)启动有所了解,那是因为启动一个应用程序首先要保证该应用程序的进程已经被启动.AMS在启动应用程序时,会先检查应用程序进程是否存在,如果不存在就需要请求Zygote进程创建并启动应用程序进程.这里我不会贴上大段大段的代码,只是一些总结,并提供了相关源码的链接. 应用程序进程(AppProcess)启动 启动大纲 AMS发送启动应用程序进程请求. Z

第二人生的源码分析 12 天空显示的实现

在虚拟世界里,自然现象的实现是最需要实现的,比如天空的实现,以便反映是白天还是晚上,这样才逼真反映现实世界.在第二人生里实现的天空,还是比较好的,如下图所示: 蔡军生 2008/01/10 QQ:9073204 深圳 从上面的图片里,可以看到太阳在远处,并具有雾化的效果,这是早上太阳升起的效果.看到远处是浅蓝色的天空,与海边连接成一体.在室外场境的模拟中,最重要的就是天空体的实现.目前实现天空体有两种不同的实现方式:天体盒和天空穹.而第二人生里是采用天空盒的实现方式,这种方式是渲染的速度比较快,

第二人生的源码分析 1 第一个画面

第二人生是一款3D为界面的虚拟世界产品,下面先来感受一下这个界面带来巨大的真实性: 通过个画面,可以看到太阳,树,人,椅是那么的逼真,这些都是通过3D技术实时显示出来的,因此对电脑的硬件需求比较高,特别对显示卡的需求更高,同时对网络的带宽也要求比较高,不过,随着技术的发展,已经具备这样的条件了.现在最流行的配置,比如3000元左右的电脑,就已经显示得不错了. 在第二人生这个虚拟世界里,强调的就是跟现实世界差不多,但比现实的东西更多一些梦想.比如在这个虚拟世界里使用的货币,是跟现实世界里的货币(美

【源码分析】动态分析 C 程序函数调用关系

By Falcon of TinyLab.org 2015/04/15 缘由 源码分析是程序员离不开的话题.无论是研究开源项目,还是平时做各类移植.开发,都避免不了对源码的深入解读. 工欲善其事,必先利其器. 之前已经介绍了如何通过 Callgraph 静态分析源代码,这里介绍如何分析程序运行时的实际函数执行情况,考虑到应用部分和内核部分有比较大的差异,该篇先介绍应用部分. 主要介绍三款工具,一款是 gprof,另外一款是 valgrind,再一款则是能够把前两款的结果导出为 dot 图形的工具

源码分析:动态分析 Linux 内核函数调用关系

源码分析:动态分析 Linux 内核函数调用关系 时间 2015-04-22 23:56:07  泰晓科技 原文  http://www.tinylab.org/source-code-analysis-dynamic-analysis-of-linux-kernel-function-calls/ 主题 Linux源码分析 By Falcon ofTinyLab.org 2015/04/18 缘由 源码分析是程序员离不开的话题. 无论是研究开源项目,还是平时做各类移植.开发,都避免不了对源码的

Android应用程序启动过程——Launcher源码分析

当我们在Launcher界面单击一个应用程序图标时就会启动一个程序,那这一个过程究竟发生了些哪样呢?让我们跟踪Launcher源码来分析一下吧. 先上流程图: step1.追踪Launcher  从源码中我们可以发现Launcher其实也是一个程序,它继承于Activity.找到该文件中的onCreate()方法,代码片段如下: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSta

Hadoop源码分析—— Job任务的程序入口

这篇文章大致介绍Hadoop Job的程序是如何启动的. 通常用Java编写的Hadoop MapReduce程序是通过一个main方法作为程序的整个入口,如下: public static void main(String[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new CalculateSumJob(),args); System.exit(res);} 可以看到这个Job任务的MapR

基于TCP网络通信的自动升级程序源码分析-客户端请求服务器上的升级信息

每次升级,客户端都会获取服务器端存放在upgradefile文件夹下的需要升级的文件和升级信息配置文件(即upgradeconfig.xml文件) 我们来看一下代码 //升级信息配置文件相对应的类 ( 升级信息配置文件是由这个类转化成的) private UpgradeConfig upgradeConfig = null; //客户端存储升级配置文件的地址 是放在客户端根目录下的 (就是把服务器 upgradefile/upgradeconfig.xml下载到客户端存放的位置) string

基于TCP网络通信的自动升级程序源码分析-启动升级文件下载程序

升级程序启动后,首先会连接服务器 private void Connect() { try { int port = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Port"]); connnectionInfo = new ConnectionInfo(IPAddress, port); connection = TCPConnection.GetConnection(connnectionInfo)