本文将介绍debug调试相关的内容,包括调试器、性能分析、堆跟踪、跟踪事件等;

  alias.h:Alias函数,提供防止载微软的编译器优化某参数变量的操作,内部通过#pragma optimize("", off)与#pragma optimize("", on)来实现关闭所有的优化选项,再恢复它们到原始(或默认)的设定;事实上Alias内部未实现任何的操作。

  stack_trace.h:

  EnableInProcessStackDumping: 开启堆栈转储于控制台输出,当可用时进程将被立即停止,仅用于单元测试中且因非线程安全,仅主线调用。针对windows版本,通过调用SetUnhandledExceptionFilter来设置异常捕获函数StackDumpExceptionFilter,其内部为重定向至控制台输出;

  StackTrace:堆栈轨迹类,堆栈轨迹假如你需要打印出某个时间的调用堆栈状态,对象创建位置等,

  首先介绍私有成员变量:

  1. kMaxTraces, trace_[kMaxTraces]:堆栈踪迹最大缓冲区大小, MSDN介绍kMaxTraces应小于63,故内部取值最大为62;

  2. count_:实际有效踪迹帧数;

  3. 不带参数的构造函数StackTrace,内部调用CaptureStackBackTrace,使用当前的调用状态下的堆栈;

  4. 带参构造函数StackTrace,重载了两个版本;其中StackTrace(const void* const* trace, size_t count),通过一个已存在的堆栈轨迹指针地址创建,此外针对windows版本的还提供了StackTrace(_EXCEPTION_POINTERS* exception_pointers),由一个异常对象创建,并调用StackWalk64获取堆栈轨迹信息,内部针对32位和64位实现;

  5. Addresses:获取当前调用堆栈轨迹信息地址;

  6. PrintBacktrace、OutputToStream:打印堆栈轨迹信息至stderr标准错误输出流;

  7. ToString:获取当前堆栈轨迹、符号信息字符串;

  debugger.h:

  1. SpawnDebuggerOnProcess:提供开始注册系统级的JIT即时调试器,并将其附加到指定的进程中;可以看到内部提供跨平台的版本,微软和posix版本;微软版本通过访问注册表HKEY_LOCAL_MACHINE下SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug中的键为Debugger的值,如"C:\windows\system32\vsjitdebugger.exe" -p %ld -e %ld,其中vsjitdebugger.exe为微软的VS即时调试器,参数-p %ld为将要调试的进程ID,-e %ld为可执行程序的进程ID,实际上可以指定一样的进程ID值即可,此后创建新的进程开启该调试;posix版本调用系统函数system,参数xterm -e 'gdb --pid=%u' &,也为进程ID,gdb调试工具。

  2. WaitForDebugger:等待指定的时间秒wait_seconds则返回,或设置参数silent为false时,则若调试器检查到抛出异常则进入调试;内部采用for循环次数为至多10*wait_seconds次,每次等待100毫秒,刚好wait_seconds秒,并循环检查BeingDebugged(若指定进程被attach运行于调试器时,返回值为真);

  3. BeingDebugged:提供不同版本,微软版本通过IsDebuggerPresent函数判断(判断调用进程是否由用户模式的调试器调试,实际上);其他版本细分为linux、BSD、ANDROID等版本,暂不细说明;

  4. BreakDebugger:提供不同版本,微软版本通过__debugbreak,暂停程序执行,打开调试器,进入调试模式;

  5. SetSuppressDebugUI,IsDebugUISuppressed目前用在UI界面是否测试设置的操作。

  debug_on_start_win.h:

  1. 提供了一个在开启运行程序时刻支持调试的类,仅提供Init,FindArgument静态接口实现;通过命令行的方式调试,至多等待时间60s进入调试;而对于命令行调试进程则等待被调试调用。目前其他地方或项目项目暂未使用到该类提供的功能。

  crash_logging.h:主要是提供一些用来添加一些元数据信息至上传负载,并将崩溃信息报告发送至崩溃服务器

  1. ScopedCrashKey:一个封装崩溃键的范围器,不允许赋值构造和复制拷贝,主要用来设置某对象的指定键的值并管理键值对的生命期,析构时清除该对象;内部调用SetCrashKeyValue(key, value)、ClearCrashKey(key)。

  2. CrashKey:用来被注册使用的,提供参数key_name作为崩溃键值名,max_length指定键值最大长度,若超过该长度则被截断;此外若该键值长度超过“chunk_max_length”但小于max_length,则会被拆分为多个块。

  3. g_crash_keys_:std::map<base::StringPiece, CrashKey>类型的全局变量指针,作为崩溃键名字的入口,分别为键与崩溃键值名;

  4. g_chunk_max_length_:单个块的最大长度;

  5. g_set_key_func_:用来设置键值对的函数;

  6. g_clear_key_func_:用来清理键值对的函数;

  7. kLargestValueAllowed:最大的max_length允许长度,1024字节;

  8. LookupCrashKey:查找g_crash_keys_中指定键的CrashKey;

  9. ChunkCrashKeyValue:辅助函数,主要用来给指定的键值名分块;内部现实为:直接截取value的crash_key.max_length长度的值,并按照chunk_max_length对截取的值分块保存至std::vector<std::string>中;

  10. SetCrashKeyValue:通过LookupCrashKey查找到崩溃键值名,若键值名不存在或键值名长度小于g_chunk_max_length_,则调用g_set_key_func_设置崩溃元数据中指定的键值对;否则对键值名截断并拆分为多个块,对于多余的,将通过g_clear_key_func_调用,各个块则调用g_set_key_func_设置块键。

  11. ClearCrashKey:清除g_crash_keys_中指定的崩溃键值名,处理的方式类似于SetCrashKeyValue,内部改为调用g_clear_key_func_实现清理工作;

  12. SetCrashKeyToStackTrace:将记录的堆栈轨迹信息写入知道的崩溃键值名crash Key中;

  13. SetCrashKeyFromAddresses:针对12,分别取出记录的堆栈信息并按照空格隔开写入崩溃键值名中;

  14. InitCrashKeys:在使用崩溃键记录前需要调用的,所有需要用到的崩溃记录键都需要被注册,注册到g_crash_keys_,参数keys为崩溃键数组,count为最大记录数,chunk_max_length为单个块最大长度;

  15. ResetCrashLoggingForTesting:重置崩溃键系统,可被重新初始化(再次调用InitCrashKeys),一般用在测试中。  

  使用示例;

  

     base::debug::StackTrace trace;
std::ostringstream os;
trace.OutputToStream(&os);
std::string backtrace_message = os.str();
std::cout << backtrace_message << std::endl;
std::cout << trace.ToString() << std::endl;
size_t frames_found = ;
trace.Addresses(&frames_found); {
base::debug::StackTrace trace;
std::ostringstream os;
trace.OutputToStream(&os);
std::cout << os.str() << std::endl;
}
 std::map<std::string, std::string>* key_values_ = NULL;

 class CrashLoggingTest
{
public:
CrashLoggingTest()
{
key_values_ = new std::map<std::string, std::string>;
base::debug::SetCrashKeyReportingFunctions(
&CrashLoggingTest::SetKeyValue,
&CrashLoggingTest::ClearKeyValue);
} virtual ~CrashLoggingTest()
{
base::debug::ResetCrashLoggingForTesting(); delete key_values_;
key_values_ = NULL;
} private: static void SetKeyValue(const base::StringPiece& key,
const base::StringPiece& value)
{
(*key_values_)[key.as_string()] = value.as_string();
} static void ClearKeyValue(const base::StringPiece& key)
{
key_values_->erase(key.as_string());
}
}; CrashLoggingTest crashLog; const char* kTestKey = "test-key";
base::debug::CrashKey keys[] = { { kTestKey, } };
base::debug::InitCrashKeys(keys, arraysize(keys), ); base::debug::SetCrashKeyValue(kTestKey, "value");
bool res = false;
res = "value" == (*key_values_)[kTestKey]; base::debug::ClearCrashKey(kTestKey);
res = (key_values_->end() == key_values_->find(kTestKey)); key_values_->clear();
delete key_values_;

  leak_tracker.h:泄露跟踪者,一个用来验证一个类的所有实例是否被安全销毁的助手,在单线程使用中比较有用,若有泄露,则每个实例的内存分配将会被写入日志;在使用时ENABLE_LEAK_TRACKER宏需要定义,否则将无效且不会记录调用堆栈信息。

   使用方式比较简单,如:

  

 class A
{
// ...
private:
base::LeakTracker<A> leak_tracker_;
};

  此后通过调用 LeakTracker<A>::CheckForLeaks()来检查是否所有实例被销毁;对于失败时,有泄露,则每个实例的内存分配将会被写入日志。

  事实上,日志记录堆栈信息,内部采用StackTrace allocation_stack_成员记录堆栈踪迹;

  LeakTracker:模板类,继承于LinkNode,即之前我们接触的堆栈列表容器,如:template<typename T> class LeakTracker : public LinkNode<LeakTracker<T> > ;

  首先,成员变量allocation_stack_,用来记录堆栈踪迹;

  静态成员函数:

  1. instances:生成对应模板类型的static LinkedList<LeakTracker<T> > list实例,它主要用来保存所有创建的实例(实际上是保存该实例下的成员变量leak_tracker_,来达到记录实例数和是否存在的状态);

  2. CheckForLeaks:用来检测当前是否所有实例已被销毁,否则打印实例内存分配堆栈踪迹信息至日志文件,实时上针对每个实例内部只打印了三条堆栈踪迹;

  3. NumLiveInstances:得到当前存活的实例数目;

  构造函数LeakTracker:内部list->append(this),追加当前实例至静态变量list中;析构函数~LeakTracker:通过this->RemoveFromList()从list中移除本对象实例;

  使用示例:

  

 class ClassA
{
private:
LeakTracker<ClassA> leak_tracker_;
}; bool res = false;
int num = LeakTracker<ClassA>::NumLiveInstances(); // num == -1; ClassA a1;
num = LeakTracker<ClassA>::NumLiveInstances(); // num == 1
scoped_ptr<ClassA> a2(new ClassA);
num = LeakTracker<ClassA>::NumLiveInstances(); // num == 2
a2.reset();
num = LeakTracker<ClassA>::NumLiveInstances(); // num == 1 LeakTracker<ClassA>::CheckForLeaks();// leaks!!!

  总结:因其继承于LinkNode,之前在讨论容器部分时对LinkNode有说明,其限制条件和LeakTracker一致的:不要用相同的指针对象。

Google之Chromium浏览器源码学习——base公共通用库(四)的更多相关文章

  1. Google之Chromium浏览器源码学习——base公共通用库(二)

    上次提到Chromium浏览器中base公共通用库中的内存分配器allocator,其中用到了三方库tcmalloc.jemalloc:对于这两个内存分配器,个人建议,对于内存,最好是自己维护内存池: ...

  2. Google之Chromium浏览器源码学习——base公共通用库(三)

    本节将介绍base公共通用库中的containers,其包含堆栈.列表.集合.以及Most Recently Used cache(最近使用缓存模板). linked_list.h:一个简单的列表类型 ...

  3. Google之Chromium浏览器源码学习——base公共通用库(一)

    Google的优秀C++开源项目繁多,其中的Chromium浏览器项目可以说是很具有代表性的,此外还包括其第三开发开源库或是自己的优秀开源库,可以根据需要抽取自己感兴趣的部分.在研究.学习该项目前的时 ...

  4. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  5. Golang源码学习:调度逻辑(四)系统调用

    Linux系统调用 概念:系统调用为用户态进程提供了硬件的抽象接口.并且是用户空间访问内核的唯一手段,除异常和陷入外,它们是内核唯一的合法入口.保证系统的安全和稳定. 调用号:在Linux中,每个系统 ...

  6. Java并发包源码学习之AQS框架(一)概述

    AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.con ...

  7. [tomcat7源码学习]初始化之catalina.home和catalina.base(转)

    我们在代码中为了获取某个配置文件路径下的文件经常会这么写 String tomcatPath = System.getProperty("catalina.home") + &qu ...

  8. Tomcat源码学习

    Tomcat源码学习(一) 转自:http://carllgc.blog.ccidnet.com/blog-htm-do-showone-uid-4092-type-blog-itemid-26309 ...

  9. 【 js 基础 】【 源码学习 】源码设计 (持续更新)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...

随机推荐

  1. 【BZOJ 4561】【JLOI 2016】圆的异或并

    http://www.lydsy.com/JudgeOnline/problem.php?id=4561 一开始并不会做,后来看题解看懂了. 看懂了之后还是错了好几次,数组大小手残开小了. 圆的包含并 ...

  2. 关于Deprecated: mysql_result: The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in

    require_once('connect.php'); $sql = "select * from introduce"; \(query = mysql_query(\)sql ...

  3. MacTalk阅读有感

    MacTalk by 池建强 高手的思维境界 -贴地气 -有思想 技术普及 文字是表达人思想的载体,池老师将自己的经历,经验分享给大家,很值得大家学习,虽然我只是个初出茅庐的小菜,现在有指路明灯一样. ...

  4. Linux文件计数

    1.当前目录下的文件数 ls -l |grep "^-"|wc -l 2.当前目录的目录树 ls -l |grep "^d"|wc -l 3.当前目录文件数包含 ...

  5. mysql日期格式化

    DATE_FORMA T(date, format) 根据格式串format 格式化日期或日期和时间值date,返回结果串. 可用DATE_FORMAT( ) 来格式化DATE 或DATETIME 值 ...

  6. 加载dll过程中assembly失败

    错误现象: 进行插件读取时出现错误:“尝试从一个网络位置加载程序集,在早期版本的 .NET Framework 中,这会导致对该程序集进行沙盒处理.此发行版的 .NET Framework 默认情况下 ...

  7. WIN10 CMD 启动虚拟WIFI

    1.以管理员身份运行命令提示符: 快捷键win+R→输入cmd→回车 2.启用并设定虚拟WiFi网卡: 运行命令:netsh wlan set hostednetwork mode=allow ssi ...

  8. [转载]抓包,端口镜像,monitor session命令(转)

    原文地址:抓包,端口镜像,monitor session命令(转)作者:浮云皓月 一.SPAN简介 SPAN技术主要是用来监控交换机上的数据流,大体分为两种类型,本地SPAN和远程SPAN. --Lo ...

  9. UITableViewCell的重用机制

    UITabelView一般会显示大量数据,如果有多少条数据就新建多少个cell,那么对于内存来说是种极大的负担,这样自然是不合理的,所以才会有重用机制 比如一个家庭办酒席,一共有13桌,每桌20个菜, ...

  10. [nosql之缓存memcache]安装篇LInux for Windows

    首先呢在PHP开发的过程中会用到很多缓存服务,从而提升访问质量或者临时存储一些数据. 优点 结构简单,读取速度快,易于维护.还有一些特性memcache redis mongodb都可以用来做为缓存用 ...