紧接着上次的问题,上次的问题其实很简单,就是HelloWorld.exe运行失败,而本文的目的,就是成功调试HelloWorld这个控制台应用程序。

  通过我的寻找,其实是一个名为TryRun的文件出了问题,那但是我们还需要知道前因后果,而并不是单个的问题哦。首先你必须看这篇文章 把CoreCLR的调试环境配置好,然后才能去调试,我们按一下F11,开始我们的调试之旅。

  如果你修改过CoreCLR的代码,别忘了生成项目,否则会出现如下错误,其实,改改底层真的很酷。千万别重新生成整个解决方案,会很费时间 = =。

  碰到了上图的问题,怎么解决呢?这是由于文件不是最新的造成的原因,因为我们加载exe和pdb是从Product文件夹下面去加载,但是其实每次生成的并不在Product底下,而是在这里面\bin\obj\Windows_NT.x64.Debug\src\coreclr\hosts\corerun\Debug,EXE文件和pdb文件都需要复制的,别漏掉了~~~

  终于开始我们的调试之旅了~~~代码我还是打算和以前一样,一个步骤写一部分~~下面的Argv其实指的是启动项目->属性->调试当中的“命令”部分,而newArgv其实指的是“工作目录”部分,有兴趣研究的可以去看我写的上一篇博文,有详细的介绍argv+1其实是把它的地址向高位移动wchar_t个字节,也就是32位,大家可以看下面图的地址变化。

int __cdecl wmain(const int argc, const wchar_t* argv[])
{
// Parse the options from the command line bool verbose = false;
bool waitForDebugger = false;
bool helpRequested = false;
int newArgc = argc - 1;
const wchar_t **newArgv = argv + 1; }

  参数释义:

  • Verbose - 打印出运算过程(日志),可以类比EF中从Nuget控制台里面migration时的verbose.
  • WaitForDebugger 运行参数,等待调试;
  • helpRequested 运行参数,帮助 ;

  下面我们来看如下代码;看了如下的代码,你还能淡定的说,Lambda表达式是.NET独有的吗?如果你还没有接触过c++中的Lambda,那么建议你看看这篇文章。下面的你就可以简单的理解为,比较2个字符串是否相等。

    auto stringsEqual = [](const wchar_t * const a, const wchar_t * const b) -> bool {
return ::_wcsicmp(a, b) == 0;
};

  当然,上面的Lambda表达式,其实是为下面的代码服务的,这些都是option,类似你在CMD里面敲了一个命令,后面还带了一些参数 比如 abc.exe -h.注意,这里的LAMBDA表达式不是写完就立即运行的,它只相当于一个方法的声明,也就是相当于你写了一个巨复杂的委托,但是没有用到过。

    auto tryParseOption = [&](const wchar_t* arg) -> bool {
if ( stringsEqual(arg, W("/v")) || stringsEqual(arg, W("-v")) ) {
verbose = true;
return true;
} else if ( stringsEqual(arg, W("/d")) || stringsEqual(arg, W("-d")) ) {
waitForDebugger = true;
return true;
} else if ( stringsEqual(arg, W("/?")) || stringsEqual(arg, W("-?")) || stringsEqual(arg, W("-h")) || stringsEqual(arg, W("--help")) ) {
helpRequested = true;
return true;
} else {
return false;
}
};

  下面的代码才开始用到,下面的代码是循环去找参数,因为有可能你的命令不止一个参数。

    while (newArgc > 0 && tryParseOption(newArgv[0])) {
newArgc--;
newArgv++;
}

  大家可能会很感兴趣,为什么这里的arg的个数是2?,哈哈,这就要问.NET中的main函数了,我也不知道为什么,不过从下面的代码可以得知,main函数至少需要2个参数。

    if (argc < 2 || helpRequested || newArgc==0) {
showHelp();
return -1;
}

  经过了一系列的准备工作,我们终于可以进入TryRun方法了。

auto success = TryRun(newArgc, newArgv, log, verbose, waitForDebugger, exitCode);

  下面的注释也已经写了,有关HostEnvironment的介绍,不过因为我当时的随笔记录的是比较老的东西,所以新东西的话会有所不同,不过 意思大同小异。

    // Assume failure
exitCode = -1; //宿主环境(这个大家有没有印象呢?我在以下随笔中有介绍过),不过当时是在coreconsole这个文件里面
//http://www.cnblogs.com/kmsfan/p/5507149.html
HostEnvironment hostEnvironment(&log);

  首先是检查有没有命令参数,当然是从外面传进来的。

	//寻找指定的EXE文件,使用LoadLibraray去完成。
const wchar_t* exeName = argc > 0 ? argv[0] : nullptr;
if(exeName == nullptr)
{
log << W("No exename specified.") << Logger::endl;
return false;
}

  然后我们看到定义了如下的一些路径,当然最后一个我暂时还不知道什么意思;

    StackSString appPath; //应用程序路径
StackSString appNiPath; //包含ni结尾的应用程序的路径
StackSString managedAssemblyFullName; //托管程序集的全名
StackSString appLocalWinmetadata;

  下面是StackSString的介绍,意思是把这些string类型的数据存放在栈的空闲区域作为预处理缓冲(不止翻译得对不对)。它还可以规定最大大小,比如这个是最大512个字节的字符串。

// ================================================================================
// StackSString is a lot like CQuickBytes. Use it to create an SString object
// using some stack space as a preallocated buffer.
// ================================================================================ typedef InlineSString<512> StackSString;

  关于NULL的值到底是什么,这里还是有讲究的,如果是C++,那么就是0 如果不是C++,那么就是void类型的指针。

wchar_t* filePart = NULL; //文件部分

//定义在vcruntime.h中
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

  下面也是一个类似的定义。

COUNT_T size = MAX_LONGPATH; //定义初始大小

//定义在palclr.h中
#define MAX_LONGPATH 260 /* max. length of full pathname */

  再来看看如下代码,我们可以从代码当中去看看appPathPtr是什么,那么,我想,会不会是因为HelloWorld的路径有误呢 ?经过我发现,文件还是有的,所以排除此原因。

    wchar_t* appPathPtr = appPath.OpenUnicodeBuffer(size - 1);
DWORD length = WszGetFullPathName(exeName, size, appPathPtr, &filePart);

  下面就是一系列判参~~

//如果长度大于规定的最大长度
//注意这2个if是都可能执行到的~~
if (length >= size)
{
appPath.CloseBuffer();
size = length;
appPathPtr = appPath.OpenUnicodeBuffer(size - 1);
length = WszGetFullPathName(exeName, size, appPathPtr, &filePart);
}
if (length == 0 || length >= size) {
log << W("Failed to get full path: ") << exeName << Logger::endl;
log << W("Error code: ") << GetLastError() << Logger::endl;
return false;
}

  今天不写太多了我就告诉大家哪里出了问题,是下面的代码出了问题,这个代码在corehost.cpp里面,属于cee_dac这个工程,但是我没有找到这个工程调试的入口,谷歌也找不到,如果有人知道,那就下面留言告诉我。

    hr = host->Start();

  

C++随笔:从Hello World 探秘CoreCLR的内部(1)的更多相关文章

  1. 【随笔】CLR:.net的类型,内部到底长啥样?

    前言 一提到.net的类型,首当其冲的就是“引用类型”.“值类型”:我们在面试中,也会经常被问“来说说值类型和引用类型....”,这时候第一反应就是:“哎呀,这还不简单,值类型是传递的值的copy,值 ...

  2. 【置顶】CoreCLR系列随笔

    CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...

  3. CoreCLR源码探索(二) new是什么

    前一篇我们看到了CoreCLR中对Object的定义,这一篇我们将会看CoreCLR中对new的定义和处理 new对于.Net程序员们来说同样是耳熟能详的关键词,我们每天都会用到new,然而new究竟 ...

  4. CoreCLR源码2

    CoreCLR源码 前一篇我们看到了CoreCLR中对Object的定义,这一篇我们将会看CoreCLR中对new的定义和处理new对于.Net程序员们来说同样是耳熟能详的关键词,我们每天都会用到ne ...

  5. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  6. C++随笔:.NET CoreCLR之GC探索(3)

    有几天没写GC相关的文章了哈,今天我讲GC的方式是通过一个小的Sample来讲解,这个小的示例代码只有全部Build成功了才会有.地址为D:\coreclr2\coreclr\bin\obj\Wind ...

  7. C++随笔:.NET CoreCLR之corleCLR核心探索之coreconsole(2)

    这篇文章是上篇的续集,本文将会继续介绍coreconsole.cpp里面的逻辑.也许大家会看一些CLR的书,我承认我没有看过,因为我觉得一个人,他再NB,那也是他自己的眼光,而且说句难听的,CLR也不 ...

  8. C++随笔:.NET CoreCLR之corleCLR核心探索之coreconsole(1)

    一看这个标题,是不去取名有点绕呢?或者是,还有些问题?报告LZ...你的标题取得有问题,是个病句!↖(^ω^)↗!!!先不要急,其实我今天带给大家的就是CoreCLR中的coreclr.其中它是在名字 ...

  9. C++随笔:.NET CoreCLR之GC探索(1)

    一直是.NET程序员,但是.NET的核心其实还是C++,所以我准备花 一点时间来研究CoreCLR和CoreFX.希望这个系列的文章能给大家带来 帮助. GC的代码有很多很多,而且结构层次对于一个初学 ...

随机推荐

  1. Restful资源文章

    理解RESTful架构 RESTful API设计指南 RESTful架构详解 NodeJs的RESTful API

  2. .NET 提升教育 第一期:VIP 付费课程培训通知!

    为响应 @当年在远方 同学的建议,在年前尝试进行一次付费的VIP培训. 培训的课件:点击下载培训周期:10个课程左右,每晚1个半小时培训价格:1000元/人.报名方式:有意向的请加QQ群:路过秋天.N ...

  3. SQLServer事务同步下如何收缩日志

    事务同步是SQLServer做读写分离的一种常用的方式. 随着业务数据的不断增长,数据库积攒了大量的日志,为了腾出硬盘空间,需要对数据库日志进行清理 订阅数据库的日志清理 因为订阅数据库所有的数据都来 ...

  4. win8.1硬盘安装ubuntu14.04双系统

    在网上找了很多方法都失败了,原因是大多数方法都是用mbr方式安装的,如grub4dos,easybcd.以至于连自己都怀疑win8能不能用硬盘安装,差点就去买个u盘来安装了,就在打算放弃的时候在ubu ...

  5. SQL Server 2016白皮书

    随着SQL Server 2016正式版发布日临近,相关主要特性通过以下预览学习: Introducing Microsoft SQL Server 2016 e-bookSQL Server 201 ...

  6. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  7. 云瓣影音网站&&微信端(已开源)

    随着该项目的发布到线上(小打小闹),即将又要开启另一段崭新的旅程.强迫自己停下来写写所学所得,个人认为总结和分享是一种很棒的学习方式.那让我们先来瞧瞧项目长的什么样.如果着急要源码的朋友,可以下拉到最 ...

  8. C# BackgroundWorker 详解

    在C#程序中,经常会有一些耗时较长的CPU密集型运算,如果直接在 UI 线程执行这样的运算就会出现UI不响应的问题.解决这类问题的主要途径是使用多线程,启动一个后台线程,把运算操作放在这个后台线程中完 ...

  9. 张小龙宣布微信小程序1月9日发布,并回答了大家最关心的8个问题

    2016 年 12 月 28 日,张小龙在微信公开课 PRO 版的会场上,宣布了微信小程序的正式发布时间. 微信小程序将于 2017 年 1 月 9 号正式上线. 同时他解释称,小程序就像PC时代的网 ...

  10. 报错:You need to use a Theme.AppCompat theme (or descendant) with this activity.

    学习 Activity 生命周期时希望通过 Dialog 主题测试 onPause() 和 onStop() 的区别,点击按钮跳转 Activity 时报错: E/AndroidRuntime: FA ...