亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1855 | 回復(fù): 0
打印 上一主題 下一主題

一個(gè)簡單的 console logger 和 stack tracer [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2006-09-19 04:37 |只看該作者 |倒序?yàn)g覽
一個(gè)簡單的 stack trace 例程,C/C++ 兩套接口
debug.h,前半是 C 接口,后半是 C++ 接口
  1. #ifndef DEBUG_H
  2. #define DEBUG_H

  3. #include <unistd.h>
  4. #include <pthread.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <stdarg.h>
  8. #include <assert.h>

  9. #ifdef __cplusplus
  10. extern "C" {
  11. #endif

  12.   // Will enable seperate output for each thread, set default level to EMERG
  13.   int dbg_enable ();

  14.   // Logging output control level. EMERG can't be hided. GETVAL retrieves current value without changing.
  15.   typedef enum {GETVAL = -1, EMERG = 0, ERROR, WARNING, INFO, DEBUG, NUM_LEVELS} dbg_level_t;

  16.   dbg_level_t dbg_level ( dbg_level_t newlvl );

  17.   // Setting prefix / postfix for each message.
  18.   void dbg_set_decorate ( char *dec[NUM_LEVELS * 2] );

  19.   // Output function.
  20.   int dbg_printf ( dbg_level_t lvl, const char *fmt, ... );

  21.   // Print stack point info with current thread's output.
  22.   int dbg_dump_stacktrace ();

  23.   void __dbg_enter (const char *file, const char *func, int line);

  24.   // Setting / cancelling stack point. C++ should use DECLARE_TRACEPOINT() macro
  25.   #define dbg_enter() do { __dbg_enter(__FILE__,__FUNCTION__,__LINE__); } while(0)
  26.   void dbg_leave ();

  27. #ifdef __cplusplus
  28. }
  29. #endif

  30. #ifdef __cplusplus

  31. #include <string>
  32. #include <list>

  33. using namespace std;

  34. // Prefered C++ interface to tracepoint. "name" is an identifier that won't conflict
  35. // within the scope of calling.
  36. #define DECLARE_TRACEPOINT(name) tracepoint name (__FILE__, __FUNCTION__, __LINE__)

  37. struct tracepoint
  38. {
  39.   tracepoint ( const char *file, const char *function, int line);
  40.   tracepoint ( const tracepoint& other );

  41.   ~tracepoint ();

  42.   tracepoint & operator= ( const tracepoint & other );

  43.   private:
  44.   int *cnt;
  45. };

  46. #endif // __cplusplus

  47. #endif // DEBUG_H
復(fù)制代碼


debug.cpp,實(shí)現(xiàn)部分,C++ 代碼

  1. #include "debug.h"

  2. static pthread_key_t debug_key;
  3. static pthread_once_t key_init_once = PTHREAD_ONCE_INIT;

  4. const char *default_dec[NUM_LEVELS * 2] = {
  5.   "\033[31mEMERG\033[0m\t", "",
  6.   "\033[33mERROR\033[0m\t", "",
  7.   "\033[36mWARNING\033[0m\t", "",
  8.   "\033[34mINFO\033[0m\t", "",
  9.   "\033[35mDEBUG\033[0m\t", "",
  10. };

  11. struct tp_frame
  12. {
  13.   string file, function;
  14.   int line;

  15.   tp_frame (const char *f, const char *fn, int l)
  16.     : file(f), function(fn), line(l), cnt(0)
  17.   {}

  18.   ~tp_frame ()
  19.   { assert( cnt == 0 ); }

  20.   // Not yet used.
  21.   tp_frame *get ()
  22.   { ++cnt; return this; }

  23.   void put ()
  24.   { --cnt; }

  25. private:
  26.   int cnt;
  27. };

  28. struct debug_info
  29. {
  30.   debug_info ();
  31.   ~debug_info ();

  32.   int ready;

  33.   int fd;
  34.   FILE * fp;
  35.   dbg_level_t level;
  36.   const char *dec[NUM_LEVELS * 2];

  37.   // private use below this point

  38.   char * buf;
  39.   unsigned bufsz;

  40.   list < tp_frame *> tracestack;

  41. };

  42. debug_info::debug_info ()
  43.     : ready(false)
  44. {
  45.   fd = -1;
  46.   fp = NULL;

  47.   int fd = dup (STDERR_FILENO);
  48.   if ( fd < 0 )
  49.     goto out;
  50.   FILE *fp = fdopen (fd, "a");
  51.   if ( fp == NULL )
  52.     goto out1;

  53.   this->fd = fd;
  54.   this->fp = fp;

  55.   this->level = EMERG;

  56.   memcpy (dec, default_dec, sizeof(default_dec));

  57.   this->buf = NULL;
  58.   this->bufsz = 0;

  59.   this->ready = true;
  60.   return;

  61. out1:
  62.   close (fd);
  63. out:
  64.   (void)0;
  65. }

  66. debug_info::~debug_info ()
  67. {
  68.   if ( fp )
  69.     fclose (fp);
  70. }


  71. static void di_dtor (void *pdi)
  72. {
  73.   struct debug_info *p = (struct debug_info *)pdi;
  74.   delete p;
  75. }

  76. static void init_key ()
  77. {
  78.   pthread_key_create (&debug_key, di_dtor);
  79. }

  80. int dbg_enable ()
  81. {
  82.   int ret = 0;
  83.   pthread_once ( &key_init_once, &init_key );

  84.   debug_info *pdi = new debug_info();

  85.   ret = (pthread_setspecific (debug_key, pdi));
  86.   return ret;
  87. }

  88. dbg_level_t dbg_level ( dbg_level_t newlvl )
  89. {
  90.   struct debug_info *pdi = (struct debug_info *)pthread_getspecific(debug_key);
  91.   if ( !pdi || !pdi->ready )
  92.     return EMERG;
  93.   dbg_level_t rt = pdi->level;
  94.   if ( (rt != newlvl) && (newlvl != GETVAL) )
  95.     {
  96.       pdi->level = newlvl;
  97.       pthread_setspecific (debug_key, pdi);
  98.     }
  99.   return rt;
  100. }

  101. void dbg_set_decorate ( char *dec[NUM_LEVELS * 2] )
  102. {
  103.   struct debug_info *pdi = (struct debug_info *)pthread_getspecific(debug_key);
  104.   if ( !pdi || !pdi->ready )
  105.     return;
  106.   memcpy( pdi->dec, dec, sizeof(default_dec) );
  107. }

  108. int dbg_printf ( dbg_level_t lvl, const char *fmt, ... )
  109. {
  110.   struct debug_info *pdi = (struct debug_info *)pthread_getspecific(debug_key);
  111.   if ( !pdi || !pdi->ready )
  112.     return 0;
  113.   if ( lvl > pdi->level )
  114.     return 0;

  115.   int rt;
  116.   va_list ap;
  117.   va_start (ap, fmt);

  118.   unsigned sz = pdi->bufsz;
  119.   char *buf = pdi->buf;

  120.   if ( buf == NULL )
  121.     {
  122.       sz = 32;
  123.       buf = (char *)malloc(sz);
  124.       if ( buf == NULL )
  125.         return 0; // ENOMEM;
  126.     }

  127.   const char *pre = pdi->dec[(int)lvl * 2];
  128.   pre = pre == NULL ? default_dec[(int)lvl * 2] : pre;
  129.   const char *post = pdi->dec[(int)lvl * 2 + 1];
  130.   post = post == NULL ? default_dec[(int)lvl * 2 + 1] : post;

  131.   while ( 1 )
  132.     {
  133.       unsigned n;
  134.       if ( (n = snprintf(buf, sz, "%s%s%s", pre, fmt, post)) > sz )
  135.         {
  136.           free (buf);
  137.           sz = n + 1;
  138.           buf = (char *)malloc(sz);
  139.           if ( buf == NULL )
  140.             return 0; // ENOMEM
  141.         }
  142.       else
  143.         break;
  144.     }
  145.   pdi->buf = buf;
  146.   pdi->bufsz = sz;

  147.   rt = vfprintf (pdi->fp, pdi->buf, ap);
  148.   va_end (ap);

  149.   return rt;
  150. }

  151. tracepoint::tracepoint ( const char *file, const char *function, int line )
  152. {
  153.   tp_frame *f = new tp_frame(file, function, line);
  154.   cnt = new int(1);

  155.   debug_info *p = (debug_info *)pthread_getspecific(debug_key);
  156.   if ( p )
  157.     {
  158.       p->tracestack.push_back (f);
  159.     }
  160. }

  161. tracepoint::tracepoint ( const tracepoint & other )
  162. {
  163.   cnt = other.cnt;
  164.   ++(*cnt);
  165. }

  166. tracepoint & tracepoint::operator= ( const tracepoint & other )
  167. {
  168.   cnt = other.cnt;
  169.   ++(*cnt);
  170.   return *this;
  171. }

  172. tracepoint::~tracepoint ()
  173. {
  174.   --(*cnt);
  175.   if ( 0 == *cnt )
  176.     {
  177.       debug_info *p = (debug_info *)pthread_getspecific(debug_key);
  178.       delete p->tracestack.back();
  179.       p->tracestack.pop_back ();
  180.       delete cnt;
  181.     }
  182. }

  183. int dbg_dump_stacktrace ()
  184. {
  185.   debug_info *p = (debug_info *)pthread_getspecific(debug_key);
  186.   list < tp_frame *> &s = p->tracestack;
  187.   while ( s.size() > 0 )
  188.     {
  189.       tp_frame *pt = s.back();
  190.       dbg_printf (EMERG, "%s() at %s:%d\n", pt->function.c_str(), pt->file.c_str(), pt->line);
  191.       s.pop_back();
  192.     }
  193.   fflush(NULL);
  194.   return 1;
  195. }


  196. // Setting / cancelling stack point. C++ should use DECLARE_TRACEPOINT() macro
  197. void __dbg_enter (const char *file, const char *function, int line)
  198. {
  199.   tp_frame *f = new tp_frame(file, function, line);

  200.   debug_info *p = (debug_info *)pthread_getspecific(debug_key);
  201.   if ( p )
  202.     {
  203.       p->tracestack.push_back (f);
  204.     }

  205. }

  206. void dbg_leave ()
  207. {
  208.   debug_info *p = (debug_info *)pthread_getspecific(debug_key);
  209.   delete p->tracestack.back();
  210.   p->tracestack.pop_back ();
  211. }
復(fù)制代碼


測試?yán)蹋篊 版
  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include "debug.h"

  4. void onabrt (int sig) {
  5.   dbg_dump_stacktrace();
  6.   fflush(NULL);
  7.   _exit(127 + sig);
  8. }

  9. int main () {
  10.   // 確保出錯(cuò)的時(shí)候自動(dòng)調(diào)用 dump_stacktrace
  11.   // C++ 程序可以通過注冊(cè) SIGABRT 捕獲 uncaught_exception,獲得類似 Java 的 st 輸出
  12.   signal( SIGSEGV, onabrt );
  13.   dbg_enable(); // 啟用 debug。每個(gè)線程都必需。
  14.   dbg_enter(); // 調(diào)用 C 接口設(shè)置 stack point?梢郧短自O(shè)置多個(gè)以縮小調(diào)試范圍
  15.   printf ("%d\n", (int)sizeof(long double));
  16.   *(int *)NULL = 3; // 制造 SIGSEGV
  17.   dbg_leave(); // 與 dbg_enter() 對(duì)應(yīng)
  18.   return 0;
  19. }
復(fù)制代碼


本來設(shè)計(jì)時(shí)候是為了要一個(gè)順手的 logger,沒想到最后竟然弄了個(gè) stack trace 的東西出來:)

dbg_printf 用作輸出,會(huì)自動(dòng)加上前后綴,并且根據(jù) dbg_set_level 設(shè)置的等級(jí)確定是否輸出。默認(rèn)的前后綴是等級(jí)名稱加上 ANSI color code,在 Emacs shell / GDB 中看著像是亂碼?梢杂 dbg_set_decorate 修改。
Part of OLFS v0.3
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP