WebRTC源码分析-定位之Location

Location类提供了一个对象构建时所在位置的基础信息,是chromium项目中的https://code.google.com/p/chromium/codesearch#chromium/src/base/location.h精简版本。在WebRTC项目中位于rtc_base/location.h和rtc_base/location.cc中。

class Location { public: // Constructor should be called with a long-lived char*, such as __FILE__. // It assumes the provided value will persist as a global constant, and it // will not make a copy of it. // // TODO(deadbeef): Tracing is currently limited to 2 arguments, which is // why the file name and line number are combined into one argument. // // Once TracingV2 is available, separate the file name and line number. Location(const char* function_name, const char* file_and_line); Location(); Location(const Location& other); Location& operator=(const Location& other); const char* function_name() const { return function_name_; } const char* file_and_line() const { return file_and_line_; } std::string ToString() const; private: const char* function_name_; const char* file_and_line_; }; // Define a macro to record the current source location. #define RTC_FROM_HERE RTC_FROM_HERE_WITH_FUNCTION(__FUNCTION__) #define RTC_FROM_HERE_WITH_FUNCTION(function_name) \ ::rtc::Location(function_name, __FILE__ ":" STRINGIZE(__LINE__)) }

该类简单易懂,但是简单之中也存在一些值得注意之处:
  • 由Location的两个成员function_name_与file_and_line_可知,Location存储着对象在哪个函数中产生,对象在哪个文件的哪一行代码中产生的信息。
  • 虽然Location提供了4个构造函数,实际使用上并不会直接使用构造方法去创建Location对象,而是使用宏RTC_FROM_HERE。如果将该宏展开,会发现其等效于:Location( __FUNCTION __, __FILE __ ":" #( __LINE __)),其中 __FUNCTION __,__FILE __,__LINE __是C++编译器的内置宏定义,分别输出代码所在的函数名,文件名以及行号。
  • 上述宏相当于调用Location类的Location(const char* function_name, const char* file_and_line)构造函数,并传入了由C++内置宏静态编译时产生的字符串常量,这些常量都是long-lived char*,因此,上述构造函数没有对传入的值重新分配空间来拷贝字符串,而是简单的记录这些常量字符串的地址。同时,Location也没有提供析构函数来销毁内部function_name_以及file_and_line_所占用的空间,直到程序尽头所占空间自然释放。
  • 同上述原因,Location的拷贝构造与赋值构造也不会为内部的成员重新分配空间,没有使用深拷贝。
【WebRTC源码分析-定位之Location】Location类的源码如下所示
Location::Location(const char* function_name, const char* file_and_line) : function_name_(function_name), file_and_line_(file_and_line) {}Location::Location() : function_name_("Unknown"), file_and_line_("Unknown") {}Location::Location(const Location& other) : function_name_(other.function_name_), file_and_line_(other.file_and_line_) {}Location& Location::operator=(const Location& other) { function_name_ = other.function_name_; file_and_line_ = other.file_and_line_; return *this; }std::string Location::ToString() const { char buf[256]; snprintf(buf, sizeof(buf), "%s@%s", function_name_, file_and_line_); return buf; }

总结
  • Location类记录对象产生的函数名,文件名+行号信息。这些信息由C++编译器内置宏 __FUNCTION __,__FILE __,__LINE __提供,编译期被转化为常量字符串。
  • Location类的构造函数并不执行内存拷贝在其内部存储上述常量字符串的信息,而是简单的记录上述常量字符串的地址,同时,也没有提供析构函数以销毁上述字符串所占空间。这样可以避免反复的进行内存申请,拷贝和释放,以提升效率。
  • 实际应用上,通常通过宏定义RTC_FROM_HERE来产生Location对象,记录此时Location对象出生位置。

    推荐阅读