muduoネットワークライブラリソース再現ノート(三):baseライブラリのException.h

3187 ワード

Muduoネットワークライブラリの概要
muduoはReactorモードに基づく現代C++ネットワークライブラリであり,著者の陳碩である.非ブロックIOモデルを採用し、イベント駆動とコールバックに基づいて、原生はマルチコアマルチスレッドをサポートし、Linuxサービスエンドマルチスレッドネットワークアプリケーションの作成に適しています.muduoネットワークライブラリのコアコードは数千行しかなく、ネットワークプログラミング技術学習の段階では、muduoは非常に学習に値するオープンソースライブラリである.現在、私もこのネットワークライブラリのソースコードを勉強し始めたばかりで、この学習過程を記録したいと思っています.このネットワークライブラリのソースコードはGitHubに公開されており、ここをクリックして読むことができます.現在Github上のこのソースコードは作者にc++11で書き換えられており、私が勉強しているバージョンはc++11バージョンを使用していません.しかし、両者は大同小異で、核心思想は変化していない.ここをクリックして私のソースコードを見ることができて、もしあなたが私の前のブログに興味があれば、次の接続をクリックすることができます:muduoネットワークライブラリのソースコードの再現ノート(一):baseライブラリのTimestamp.h muduoネットワークライブラリソースコード再現ノート(二):baseライブラリのAtomic.h
Exception.h
Exceptionクラスは簡単で、異常イベントのパッケージです.クラスコードを見てみましょう.
class Exception : public std::exception
{
 public:
  explicit Exception(const char* what);
  explicit Exception(const string& what);
  virtual ~Exception() throw();
  virtual const char* what() const throw();
  const char* stackTrace() const throw();

 private:
  void fillStackTrace();  //       
  string demangle(const char* symbol);//         
  string message_; //      
  string stack_;//       
};

ここで注目すべき関数は、2つのプライベートメンバー関数fillStackTrace()とdemangle()関数です.次に分析します.
FillStack()関数
FillStack関数の役割は,現在のスレッドのスタックフレーム情報を取得し,可読性の強いコンテンツに変換して印刷することである.コードを見てみましょう.
void Exception::fillStackTrace()
{
  const int len = 200;
  void* buffer[len];
  int nptrs = ::backtrace(buffer, len);
  char** strings = ::backtrace_symbols(buffer, nptrs);
  if (strings)
  {
    for (int i = 0; i < nptrs; ++i)
    {
      // TODO demangle funcion name with abi::__cxa_demangle
      //stack_.append(strings[i]);
	  stack_.append(demangle(strings[i]));
      stack_.push_back('
'); } free(strings); } }

fillStackTrace()では、まず、関連するスタックフレーム情報を格納できる汎用ポインタ配列bufferを定義します.次にbacktrace関数を使用して、現在のスレッドのスタックフレーム情報を取得します.backtrace関数のプロトタイプは次のとおりです.
int backtrace(void **buffer, int size);

sizeパラメータは、bufferに格納できる情報の数を指定します.戻り値は、実際に返される情報の数です.次にbacktrace_を使用しますSymbolsはbufferの情報を文字列配列に変換し、関数のプロトタイプは
char **backtrace_symbols(void *const *buffer, int size);

でもbacktrace_Symbols関数が返す情報の可読性はよくありません.コンパイラは定義した関数に新しい名前を与えるので、この新しい名前を可読な名前に翻訳する必要があります.この機能はdemangle関数で完了します.
demangle関数
demangle関数の機能は前述したようにstringsの文字列情報を可読性の良い情報に翻訳するものである.コード:
string Exception::demangle(const char* symbol)
{
  size_t size;
  int status;
  char temp[128];
  char* demangled;
  //first, try to demangle a c++ name
  if (1 == sscanf(symbol, "%*[^(]%*[^_]%127[^)+]", temp)) {
    if (NULL != (demangled = abi::__cxa_demangle(temp, NULL, &size, &status))) {
      string result(demangled);
      free(demangled);
      return result;
    }
  }
  //if that didn't work, try to get a regular c symbol
  if (1 == sscanf(symbol, "%127s", temp)) {
    return temp;
  }
 
  //if all else fails, just return the symbol
  return symbol;
}

元の情報を可読性の高い情報に変換するコアの作業cxa_demangleが完了しました.関数のプロトタイプ:
char *__cxa_demangle (const char *mangled_name, char *output_buffer, size_t *length, int *status);