前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >eos源码赏析(十五):EOS源码调试及跟踪(上)

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

作者头像
用户2569546
发布2021-11-23 10:32:59
5530
发布2021-11-23 10:32:59
举报
文章被收录于专栏:eosfanseosfans

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

前期一直在对源码做分析,其中有很多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为例来看:

代码语言:javascript
复制
#define dlog( FORMAT, ... ) \
  FC_MULTILINE_MACRO_BEGIN \
   if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) \
      (fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
  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分别添加日志如下:

代码语言:javascript
复制
**"db_store_i64"**
int 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 ) {
//   require_write_lock( scope );
   const auto& tab = find_or_create_table( code, scope, table, payer );
   auto tableid = tab.id;

   EOS_ASSERT( payer != account_name(), invalid_table_payer, "must specify a valid account to pay for new record" );

   const auto& obj = db.create<key_value_object>( [&]( auto& o ) {
      o.t_id        = tableid;
      o.primary_key = id;
      o.value.resize( buffer_size );
      o.payer       = payer;
      memcpy( o.value.data(), buffer, buffer_size );
   });

   db.modify( tab, [&]( auto& t ) {
     ++t.count;
   });
   dlog("the buffer_size insert to db:${size}kbytes",("size",buffer_size));
   int64_t billable_size = (int64_t)(buffer_size + config::billable_size_v<key_value_object>);
   update_db_usage( payer, billable_size);
   keyval_cache.cache_table( tab );
   return keyval_cache.add( obj );
}
**"update_db_usage"**
void apply_context::update_db_usage( const account_name& payer, int64_t delta ) {
   string strPayer = name_to_string(payer);
   dlog("The payer name is:${name}",("name",strPayer));
   dlog("The usage ram is:${ram}",("ram",delta));
   if( delta > 0 ) {
      if( !(privileged || payer == account_name(receiver)) ) {
         require_authorization( payer );
      }
   }
   trx_context.add_ram_usage(payer, delta);
}

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

代码语言:javascript
复制
//执行的action
cleos push action tlbb.code create '["xiaofeng","1000","500","丐帮帮主","辽国"]' -p xiaofeng
//console的日志打印
2018-08-28T11:09:30.847 thread-0   apply_context.cpp:451         db_store_i64         ] the buffer_size insert to db:45kbytes
2018-08-28T11:09:30.848 thread-0   apply_context.cpp:364         update_db_usage      ] The payer name is:tlbb.code
2018-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++开发相应的插件,笔者安装了以下插件,建议朋友们也都安装下,方便以后的使用如下图:

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

代码语言:javascript
复制
./eosio_build.sh -o Debug

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

配置好Json之后我们再点左上角的三角图标就可以启动nodeos了,而后便可进行断点调试,我们知道当我们使用enable producer之后就会持续不断的出块,出块的意义暂且不考虑,我们回头看出块的过程该如何进行调试,在eos源码赏析(八):EOS智能合约入门之区块生产一文中我们提到出块其实是在controller.cpp完成的,那么我们在此处添加断点查看:

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 eosfans 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
区块链
云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档