我们知道一般的Windows程序都会有一个WinMain函数,Chrome的这个函数在chrome\app\chrome_exe_main_win.cc这个文件中:
2
3 // Initialize the commandline singleton from the environment.
4 CommandLine::Init(0, NULL);
5 // The exit manager is in charge of calling the dtors of singletons.
6 base::AtExitManager exit_manager;
7
8 MetroDriver metro_driver;
9 if (metro_driver.in_metro_mode())
10 return metro_driver.RunInMetro(instance, &RunChrome);
11 // Not in metro mode, proceed as normal.
12 return RunChrome(instance);
13 }
首先,这个函数初始化了CommandLine,它是一个singleton,用来保存和管理当前进程中的所有参数。然后又创建了一个AtExitManager,它是用来负责所有singleton的销毁工作的。若是在Win8下并满足MetroDriver的检测的话,就可能通过MetroDriver::RunInMetro来启动Chrome。下面将详细看一下用的比较多的RunChrome函数。
2 bool exit_now = true;
3 // We restarted because of a previous crash. Ask user if we should relaunch.
4 if (ShowRestartDialogIfCrashed(&exit_now)) {
5 if (exit_now)
6 return content::RESULT_CODE_NORMAL_EXIT;
7 }
8
9 // Initialize the sandbox services.
10 sandbox::SandboxInterfaceInfo sandbox_info = {0};
11 content::InitializeSandboxInfo(&sandbox_info);
12
13 // Load and launch the chrome dll. *Everything* happens inside.
14 MainDllLoader* loader = MakeMainDllLoader();
15 int rc = loader->Launch(instance, &sandbox_info);
16 loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded();
17 delete loader;
18 return rc;
19 }
RunChrome中的第一个先调用ShowRestartDialogIfCrashed,Chrome若是之前崩溃了,这个函数就互弹出一个MessageBox,告诉你崩溃的情况,是否需要再开启Chrome,若要开启,下面的代码再跑一遍,重新打开Chrome。
接下来初始化sandbox,sandbox对象创建完后,必须要用content::InitializeSandboxInfo初始化。
由于,Chrome的实际内容并不在Chrome.exe中,而在Chrome.dll中,所以下面有个创建MainDllLoader对象的过程 —— MakeMainDllLoader()。然后通过这个对象的Launch方法将整个Chrome加载起来,这个方法有两个参数:一个是WinMain中的HINSTANCE,另一个是之前创建的那个sandbox。
2 sandbox::SandboxInterfaceInfo* sbox_info) {
3 string16 version;
4 string16 file;
5 dll_ = Load(&version, &file);
6 if (!dll_)
7 return chrome::RESULT_CODE_MISSING_DATA;
8
9 scoped_ptr<base::Environment> env(base::Environment::Create());
10 env->SetVar(chrome::kChromeVersionEnvVar, WideToUTF8(version));
11
12 InitCrashReporter();
13 OnBeforeLaunch(file);
14
15 DLL_MAIN entry_point =
16 reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain"));
17 if (!entry_point)
18 return chrome::RESULT_CODE_BAD_PROCESS_TYPE;
19
20 int rc = entry_point(instance, sbox_info);
21 return OnBeforeExit(rc, file);
22 }
这个函数中,先通过Load方法将Chrome.dll加载进来,dll_中保存了DLL句柄,下面还有其他一些准备工作。接着在GetProcAddress这里进入正题了,寻找Chrome.dll这个模块中名为ChromeMain的函数,entry_point中保存了这个函数指针,最后通过调用这个函数进到Chrome.dll模块中执行剩余的工作。
本文链接
第一篇博文有点小鸡冻。在哈工程寒假集训中第一次模拟中唯一一道对我有价值的题就是大数加法,随后的几次模拟中大数运算不断,可见这是我们必须掌握的技能,本人智商较低,先讲解下大数加法减法,乘除阶乘或者结合其他知识的大数运算日后定会奉上。
究竟为什么要用大数加法呢。我们来看下数据:
bool型为布尔型,占1个字节,取值0或1。
BOOL型为int型,一般认为占4个字节,取值TRUE/FALSE/ERROR。
sbyte型为有符号8位整数,占1个字节,取值范围在128~127之间。
bytet型为无符号16位整数,占2个字节,取值范围在0~255之间。
short型为有符号16位整数,占2个字节,取值范围在-32,768~32,767之间。
ushort型为无符号16位整数,占2个字节,取值范围在0~65,535之间。
int型为有符号32位整数,占4个字节,取值范围在-2,147,483,648~2,147,483,647之间。
uint型为无符号32位整数,占4个字节,取值范围在0~4,294,967,295之间。
long型为64位有符号整数,占8个字节,取值范围在9,223,372,036,854,775,808~9,223,372,036,854,775,807之间。
ulong型为64位无符号整数,占8个字节,取值范围在0~18,446,744,073,709,551,615之间。
float型为32位单精度实数,占4个字节,取值范围3.4E+10的负38次方~3.4E+10的38次方之间。
double型为64位实数,占8个字节,取值范围1.7E+10的负308次方~1.7E+10的正308次方。
所以999999999999999999999999999999999999999+888888888888888888888888888888888888888888888=?
大数加法
基本思想:数组要多长有多长啊,随便定义个a[1000000],不就OK啦!
我都能写出来,当然代码是非常简单了啦,我说下要注意的几个问题:
1. 判断最后数组的长度
2. 去掉前导零
2 {
3 int num1[M],nm2[M];
4 int i,j;
5 len1=strlen(s1);
6 len2=strlen(s2);
7 for(i=len1-1,j=0;i>=0;i--)//num[0]保存的是低位
8 num1[j++]=s1[i]-'0';
9 for(i=len2-1,j=0;i>=0;i--)
10 num2[j++]=s2[i]-'0';
11 for(i=0;i<M;i++)
12 {
13 num1[i]+=num2[i];
14 if(num1[i]>9)
15 {
16 num1[i]-=10;
17 num1[i+1]++;
18 }
19 }
20
21 for(i=M;(i>=0)&&(num1[i]==0);i--)//找到第一个不是零的数
22 {
23 if(i>=0)
24 for(;i>=0;i--)
25 printf("%d",num1[i]);
26 else
27 printf("0\n")
28 }
当然方法不止一种。如果说上面这个清晰的话,那下面这个应该是省了点内存。
2 {
3 char c[10001];
4 int lena=strlen(a),lenb=strlen(b);
5 int i,j,len;
6 len=lena>lenb?lena:lenb;
7 len++;
8 c[0]='\0';
9 for(i=1;i<=len;i++)c[i]='0';
10 for(i=1;i<=lena;i++)c[i]+=a[lena-i]-48;
11 for(i=1;i<=lenb;i++)c[i]+=b[lenb-i]-48;
12 for(i=0;i<=len;i++)
13
今天在看《C程序设计语言》的时候写了如下一段代码
2 unsigned int a = -20;
3 printf("%d", a);
4 return EXIT_SUCCESS;
5 }
Console: -20
理论上a声明为unsigned int后不应该能显示正确的值,这里之所以能显示-20是由于在printf的格式化参数中使用了%d, 该函数会首先将a转化为int类型。
如果你对编译器的越界处理有所了解的话,应该知道这时候一般情况下,a所表示的值为4294967276(在32位机器中,int用32位bit来表示,无符号int所能表示的最大数为4294967296)
说说我所理解的编译器对上述代码的处理:
1. -20为int类型,第2行赋值语句将它强行转化为unsigned int类型, 越界,因为unsigned int和int在内存中存储的位数是一样的,因此两者在物理内存中是完全一样的。
2. 第3行printf遇到%d占位符时,即认为此处应显示一个int类型值, 于是将a又转化为int类型,所以此时显示出来的结果跟原来赋值是一样的
本文链接