eos源码赏析(十五):EOS源码调试及跟踪(上)

工欲善其事,必先利其器。

 

前期一直在对源码做分析,其中有很多eos开发入门者还未深入到这一步,于是最近后台有很多留言,问关于如何进行eos代码调试的问题,这其中涉及到调试的IDE工具以及调试的方法。

 

从个人经验来看,若要对代码进行跟踪无外乎通过日志的打印去跟踪和断点调试堆栈的调用去观察代码调用的流程。今天我们就简单的谈谈如何对代码进行跟踪调试,系列同样分为上下两篇:

上篇针对Linux和Mac下日志打印跟踪及相关调试及IDE(vscode)的使用,下篇针对Windows下使用VS这个大家耳熟能详的IDE调试eos代码。

本文主要分为以下内容:

日志打印跟踪调试

VSCode调试eos代码

 

1、日志打印跟踪调试

 

在先前的文章中我们多次提到数据的持久化存储,而其最基本的操作便是将数据表以Multi-Index的形式写入到db中,而这个数据表的大小关乎到我们在执行transaction的时候消耗的ram的大小,那么我们能否从代码中看到一些端倪呢,即数据表内容的大小和我们消耗的ram有什么直接联系呢,让我们以日志打印的形式去简单的跟踪下,获取数据表内容的大小,而和ram之间的联系,我们会在接下来的系列中做详细的分析。

我们在看源码的时候,会看到eos中根据不同的日志等级有ilog、elog、wlog、dlog等等的日志打印形式。而这几种日志有什么区别呢,我们以dlog为例来看:

1#define dlog( FORMAT, ... ) \
2  FC_MULTILINE_MACRO_BEGIN \
3   if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) \
4      (fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
5  FC_MULTILINE_MACRO_END

在logger.hpp中对日志的打印做了相应的说明,我们可以看到dlog的使用意味着日志打印功能以开启,且打印出debug形式的日志,而ilog、elog、wlog分别对应着info、error、warning,下面我们举个例子来看看如何使用log的形式对代码进行跟踪调试,在上篇文章中

eos源码赏析(十四):EOS智能合约数据持久化存储(下)

我们提到的

update_db_usage

会更新ram的使用量,我们在db_store_i64及

update_db_usage

分别添加日志如下:

 1**"db_store_i64"**
 2int apply_context::db_store_i64( uint64_t code, uint64_t scope, uint64_t table, const account_name& payer, uint64_t id, const char* buffer, size_t buffer_size ) {
 3//   require_write_lock( scope );
 4   const auto& tab = find_or_create_table( code, scope, table, payer );
 5   auto tableid = tab.id;
 6
 7   EOS_ASSERT( payer != account_name(), invalid_table_payer, "must specify a valid account to pay for new record" );
 8
 9   const auto& obj = db.create( [&]( auto& o ) {
10      o.t_id        = tableid;
11      o.primary_key = id;
12      o.value.resize( buffer_size );
13      o.payer       = payer;
14      memcpy( o.value.data(), buffer, buffer_size );
15   });
16
17   db.modify( tab, [&]( auto& t ) {
18     ++t.count;
19   });
20   dlog("the buffer_size insert to db:${size}kbytes",("size",buffer_size));
21   int64_t billable_size = (int64_t)(buffer_size + config::billable_size_v);
22   update_db_usage( payer, billable_size);
23   keyval_cache.cache_table( tab );
24   return keyval_cache.add( obj );
25}
26**"update_db_usage"**
27void apply_context::update_db_usage( const account_name& payer, int64_t delta ) {
28   string strPayer = name_to_string(payer);
29   dlog("The payer name is:${name}",("name",strPayer));
30   dlog("The usage ram is:${ram}",("ram",delta));
31   if( delta > 0 ) {
32      if( !(privileged || payer == account_name(receiver)) ) {
33         require_authorization( payer );
34      }
35   }
36   trx_context.add_ram_usage(payer, delta);
37}

我们在以上的代码中分别添加了dlog的日志,来跟踪数据表中buffer的大小以及谁为该action支付ram以及本次action所消耗的内存的大小,我们来create一张数据表出来,看看日志中打印什么内容,如下操作:

1//执行的action
2cleos push action tlbb.code create '["xiaofeng","1000","500","丐帮帮主","辽国"]' -p xiaofeng
3//console的日志打印
42018-08-28T11:09:30.847 thread-0   apply_context.cpp:451         db_store_i64         ] the buffer_size insert to db:45kbytes
52018-08-28T11:09:30.848 thread-0   apply_context.cpp:364         update_db_usage      ] The payer name is:tlbb.code
62018-08-28T11:09:30.848 thread-0   apply_context.cpp:365         update_db_usage      ] The usage ram is:157

通过在console的日志打印我们可以看到,数据表中的buffersize为45kbytes,而消耗的ram为157kbytes,是由合约账户tlbb.code来支付这些ram的消耗。以上,我们就通过dlog日志跟踪的形式来获取到了action执行的过程中ram的消耗,当然关于ram的使用及消耗有很多内容要写,比如为什么ram和buffersize的大小不一致,ram的消耗和abi文件的大小有什么关系,我们会单独拿出一个系列来写,本文只谈如何添加日志打印来跟踪代码。

2、使用VSCode调试eos代码

上面我们介绍了日志跟踪的方式来调试代码,而在以前的文章中如

eos源码赏析(八):EOS智能合约入门之区块生产

 中使用vscode的形式进行代码的调试,我们再简单的介绍下VSCode的使用,本文以Ubuntu16.04为例:

1、下载安装VSCode,关于VSCode的使用技巧有很多,不再一一介绍。
2、安装c++开发相应的插件,笔者安装了以下插件,建议朋友们也都安装下,方便以后的使用如下图:

eos源码赏析(十五):EOS源码调试及跟踪(上)_第1张图片

3、编译eos的时候加上debug选项。即在eos的路径下使用sh编译的时候加上debug选项:

1./eosio_build.sh -o Debug

4、使用VSCode打开源码,并配置相关Json,VSCode是以文件夹的形式打开整个eos项目的,如下图,结构也很清晰:

eos源码赏析(十五):EOS源码调试及跟踪(上)_第2张图片

配置好Json之后我们再点左上角的三角图标就可以启动nodeos了,而后便可进行断点调试,我们知道当我们使用enable producer之后就会持续不断的出块,出块的意义暂且不考虑,我们回头看出块的过程该如何进行调试,在

eos源码赏析(八):EOS智能合约入门之区块生产

一文中我们提到出块其实是在controller.cpp完成的,那么我们在此处添加断点查看:

通过这种方式,我们便完成了nodeos的调试,而在窗口的左侧,我们可以查看堆栈的调用、可以观察某个具体参数的值,那么我们如果要调试cleos也是一样的道理,只需修改Json中的相关参数即可:

eos源码赏析(十五):EOS源码调试及跟踪(上)_第3张图片

我们在main函数内打断点,可以在左侧看到变量的值,也可以将变量添加到监视器内,同样的可以看到堆栈调用的顺序,就方便我们进行调试工作了。

本文介绍了eos跟踪调试的两种方式,即通过日志打印的方式进行代码的跟踪,以dlog为例打印action执行中的内存消耗,以及通过VSCode对eos代码进行Debug调试的过程,以producer_plugin及cleos的main函数为例进行的调试。而本文的内容适用于Linux及Mac操作系统,对于一些Windows开发者来说,熟悉了IDE,如VS系列的IDE,能不能在Windows适用VS对eos代码进行调试呢?答案是肯定的,我们将在本系列的下篇做简单的介绍。

如你觉得我的文章对你有一定的帮助,请点击文章末尾的喜欢该作者。

如果你对eos开发感兴趣,欢迎关注本公众号,一起学习eos开发。 

eos源码赏析(十五):EOS源码调试及跟踪(上)_第4张图片

微信公众号 有任何疑问或者指教请添加本人个人微信,当然有对eos开发感兴趣或者金庸粉的也可以添加一起交流,备注eos开发或金庸。

eos源码赏析(十五):EOS源码调试及跟踪(上)_第5张图片

个人微信号

你可能感兴趣的:(C++,eos源码解析,eos源码赏析)