GDB 使用经验(二)

GDB 使用经验(二)
Hints of using GDB inside Emacs

继续前文GDB 使用经验, 这里介绍在Emacs中使用GDB的一点经验。

(1) GDB many windows mode 【1】

在M-x gdb 启动Emacs 中的GDB mode 之后,我们可以 M-x gdb-many-windows, 将GDB comand(GDB 命令)、local variable(局部变量)、source code(源程序代码)、stack(堆,用于检查函数调用的层数)、breakpoints(所有已经设置的断点)这5个有用的窗口排列起来。

如果想少打几个键,可以把下面的代码放到~/.emacs,这样以后M-x gmw 就等于是M-x gdb-many-windows了。

(defun gmw ()
"start gdb-many-windows"
(gdb-many-windows))

(2) 快捷键 Short cuts

在GDB中, 常用的命令包括continue, next等等。在Eamcs中的快捷键因窗口的不同而不同。例如,在GDB command窗口,next 的快捷键是C-x C-a C-n,而在source code窗口, next的快捷键是C-c C-n。但我们可以总结规律为基本命令都是prefix + key 的形式。

在GDB command 窗口的prefix 都是:C-c
在source code 窗口的prefix 都是:C-x C-a

key对应于next命令是: C-n
key对应于step命令是: C-s
key对应于until命令是: C-u
key对应于continue命令是: C-r
key对应于finish命令是: C-f
key对应于watch expression命令是: C-w (光标所在的变量会被watch,会出现另外一个窗口显示该变量)
key对应于print expression命令是: C-p (需要先mark一个region,这个region表示的expression表达式会被打印出来)
key对应于temporary breakpoint(临时断点)命令是: C-t
key对应于delete breakpoint(删除断点)命令是: C-d (如果当前行有断点,则删除之)

(3) Enable tools tips 【2】

在Visual Studio中另一个有用的功能是:当鼠标移动到一个变量上时,这个变量的值会通过tooltip的方式显示出来。
这个功能在GDB中也能实现。
在GUD菜单中选中”Show GUD tooltips”即可。使用效果如下:

【1】Fancy Debugging
【2】Tooltips

给主机起别名(SSH)

Give SSH hostname alias names.

当使用SSH登录远端的主机时,常常要输入长长的一串主机名,比如:xxx@wonderland.sph.umich.edu。
我发现了一个简便的方法:
在.ssh/config里面加入下面的字段:
Host won
Hotname wonderland.sph.umich.edu
这样只需要输入ssh won,就可以登录wonderland.sph.umich.edu主机了。
上面的方法可以使用ssh,sftp。

还有一个更简便的方法可以使用ssh,但不能兼顾sftp,就是用bash alias功能,比如:
alias won=’ssh xxx@wonderland.sph.umich.edu’
那么只需要输入won就可以登录了。

在命令行里发邮件(Ubuntu)

(Ubuntu) Send email from Terminal using Gmail or your domain.
本文介绍如何在命令行里通过Gmail或者你自己的域名(需要你有Google Apps)发邮件,我在Ubuntu 10.10下测试通过。

(1)安装ssmtp

(2)之后配置/etc/ssmtp/ssmtp.conf如下:

root=YOUR_EMAIL@gmail.com
mailhub=smtp.gmail.com:465
rewriteDomain=gmail.com
AuthUser=YOUR_GMAIL_USERNAME # (without @gmail.com)
AuthPass=YOUR_GMAIL_PASSWORD
FromLineOverride=YES
UseTLS=YES

特别要注意的是rewriteDomain=后面不能用包括用户名,比如root@abc.com是不允许的,但abc.com是允许的

(3)测试
以下两种方法都可以发邮件:
echo “email content” | mail -s “email subject” me@zhanxw.com
echo “email content from mutt” | mutt -s “email subject” -a ‘content.txt’ — me@zhanxw.com

主要参考翻译自:
User Gmail to Send Email

GDB 使用经验

本文介绍一些常用的GDB技巧

 

(1)使用.gdbinit

在.gdbinit里可以使用 define 命令,来简化复杂命令的输入,例如重定向stdout, stderr:
def redirect
call (void)close(1)
call (void)close(2)
call (int)open($arg0, 2)
call (int)open($arg0, 2)
end

之后就可以用

(gdb)redirect(“/dev/ttyp3”)

来把输入输出重定向到tty3 (这个/dev/tty3可以用 shell tty命令获得)
这个例子选自http://blogold.chinaunix.net/u3/111274/showart_2162256.html

此外,还可以给这个别名加上帮助说明性文字,格式为:
document user-defined-command
帮助说明性文字
end

例如:
document redirect
redirect stdout and stderr to arg0
end

.gdbinit中还可以定义hook函数(http://dev.firnow.com/course/6_system/linux/linuxjq/20090307/159416.html),
例如想在print命令前显示一段“———-”,:
define hook-print
echo ———-\n
end

.gdbinit会被GDB默认读取,如果有特定的配置文件,可以用source命令(类似bash的source命令)

(2)补充一些有用的命令

用whatis命令检查变量的类型,
ptype:比whatis的功能更强,他可以提供一个结构的定义,
commands 命中断点时,列出将要执行的命令
使用“rb”命令,如果执行“rb”时不带参数,则表示在所有函数处打一个断点,“rb”后面可以接一个符合正则表达式的参数,用来对符合正则表达式的所有函数打断点
info break 显示当前断点清单,包括到达断点处的次数等。
info files 显示被调试文件的详细信息。
info func 显示所有的函数名称。
info local 显示当函数中的局部变量信息。
info prog 显示被调试程序的执行状态。
info var 显示所有的全局和静态变量名称。
rwatch 当表达式(变量)expr被读时,停住程序。
awatch 当表达式(变量)的值被读或被写时,停住程序。
save breakpoints — Save current breakpoint definitions as a script
c [count] 表示连续(c)ontinue 多次

from: http://www.cppblog.com/true/archive/2009/01/11/71749.html

(3)print的两个技巧

(gdb)print $1 ($1为历史记录变量,在以后可以直接引用 $1 的值)
l 人为数组
人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示:
base@length
因此,要想显示在h后面的10个元素,可以使用h@10:
(gdb)print h@10
$13=(-1,345,23,-234,0,0,0,98,345,10)

http://moonwater.blogbus.com/logs/2256694.html

(4) GDB 其他应用:显示STL里的数据结构;画图等等

All from GDB wiki
美观的显示STL数据结构,比如std::string, std::vector…
http://sourceware.org/gdb/wiki/STLSupport

画one-dimensinoal图:
http://sourceware.org/gdb/wiki/PlottingFromGDB

其他有意思的extension:
比如检查libc的heap;美观的调试wxWidgets中的变量等等:
http://sourceware.org/gdb/wiki/HomePage

(5)GDB环境变量

(陈皓专栏 【空谷幽兰,心如皓月】 http://blog.csdn.net/haoel/archive/2003/07/02/2879.aspx)
你可以在GDB的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定
义一个GDB的变量很简单只需。使用GDB的set命令。GDB的环境变量和UNIX一样,
也是以$起头。如:
set $foo = *object_ptr
使用环境变量时,GDB会在你第一次使用时创建这个变量,而在以后的使用中,则直接对
其賦值。环境变量没有类型,你可以给环境变量定义任一的类型。包括结构体和数组。
show convenience
该命令查看当前所设置的所有的环境变量。
这是一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。
例如:
set $i = 0
print bar[$i++]->contents
于是,当你就不必,print bar[0]->contents, print bar[1]->contents地输入命令了。输入这样的
命令后,只用敲回车,重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功
能。

 

其他有益的参考

【1】GNU Project Debugger: More fun with GDB
此文中介绍了各种define的command,可以用来简化命令的输入。
【2】 陈皓博客:用GDB调试程序 包括的很详尽的对各种命令的介绍
【3】GDB中应该知道的几个调试方法 常用的几个GDB技巧,例如调试macro,条件断点,command命令等等。

 

BTW:

刚刚发现进入blog的时候又是白屏了,原因还是MySQL没有自动启动。
从这里找解决方法,希望管用:
http://ubuntuforums.org/showthread.php?t=1668170

sudo apt-get install sysv-rc-conf
sudo sysv-rc-conf
把mysql在level 2,3,4,5中选中。

学习和应用Google C++ Coding Style Guide (in Emacs)

Learning and applying coding style from Google (in Emacs)

今天李开复的博客转发了一条围脖,大意是:Google C++ Coding Style是最好的Coding Style,没有之一。
以前虽然经Paul提示过,但当时的我并没有提起足够的重视,现在重新看了一下,受益匪浅。
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml Google C++ Style Guide

这个Style Guide不仅提示并规定了如何格式化代码,还对C++中的特性做了对比和使用建议。例如:
(1) 对于引用(reference)的参数,应该尽量使用const来做修饰,否则我们不知道程序中修改的值会不会有超出该函数的作用;
(2) 对于要修改值的参数,则提倡使用指针。
(3) 还有,对于构造函数Constructor,Google 认为应使用explicit关键字来修饰,这样防止编译器做隐式的类型转换,同时构造函数必须明确的写出来,即使是与default的形式是相同的。
(4) 对于头文件的引用,Google 建议使用Forward declaration(提前声明)来减少包含过多的文件次数

在这个Style Guide之中,还提到了一个有用的工具cpplint.py, 这个Python工具可以对照Google Style Guide去检查你的代码是否符合规范。我是一个Emacs fans,那么如何把Google Style Guide 和 我们的.emacs配置结合起来呢?
首先你需要下载这个文件: google-c-style.el
之后考虑到我所在的小组要求Tab-indent是4个空格,并且要求用空格替代Tab,那么我们的.emacs配置如下:

(require 'cc-mode)
(require 'google-c-style)
(defun my-build-tab-stop-list (width)
  (let ((num-tab-stops (/ 80 width))
	(counter 1)
	(ls nil))
    (while (<= counter num-tab-stops)
      (setq ls (cons (* width counter) ls))
      (setq counter (1+ counter)))
    (set (make-local-variable 'tab-stop-list) (nreverse ls))))
(defun my-c-mode-common-hook ()
  (c-set-style "google")
  (setq tab-width 4) ;; change this to taste, this is what K&R uses :)
  (my-build-tab-stop-list tab-width)
  (setq c-basic-offset tab-width)
  (setq indent-tabs-mode nil) ;; force only spaces for indentation
  (local-set-key "\C-o" 'ff-get-other-file)
  (c-set-offset 'substatement-open 0)
  (c-set-offset 'arglist-intro c-lineup-arglist-intro-after-paren)
  )
;; google sytle is defined in above function
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)
(add-hook 'c++-mode-common-hook 'my-c-mode-common-hook)

如何配置.emacs里并加入cpplint功能呢?只需在.emacs里加入如下代码:

(defun cpplint ()
  "check source code format according to Google Style Guide"
  (interactive)
  (compilation-start (concat "python ~/bin/cpplint.py " (buffer-file-name))))

我们只需要执行M-x cpplint就可以得到格式检查的结果。用C-x `,或者M-g n, M-g p可以上下切换。

另一个常用的功能是如何将多个源文件通过Emacs来调整格式的(batch indent source code)?
参考 Batch Indentation with Emacs,文中提到的方法可以用默认的代码风格来格式化源文件。
但我们的目标是用Google风格来格式话代码,那么只需要稍作改变:
~/bin/emacs-format-function

;;; File: emacs-format-file
;;; Stan Warford
;;; 17 May 2006
;; from: http://www.cslab.pepperdine.edu/warford/BatchIndentationEmacs.html

;; Adopt by Xiaowei Zhan 2011 from .emacs
(require 'google-c-style)
(defun emacs-format-function ()
  "Format the whole buffer."
  (setq tab-width 4) ;; change this to taste, this is what K&R uses :)
  (setq c-basic-offset tab-width)
  (c-set-offset 'substatement-open 0)
  ;; next line is strange, I copied it from .emacs, but it cannot find c-lineup-arglist-intro-after-paren
  ;; however, disable this line seems working as well.
  ;;(c-set-offset 'arglist-intro c-lineup-arglist-intro-after-paren) 
  (indent-region (point-min) (point-max) nil)
  (untabify (point-min) (point-max))
  (save-buffer)
  )

~/bin/my-indent

#!/bin/bash
# File: my-indent
# Opens a set of files in emacs and executes the emacs-format-function.
# Assumes the function named emacs-format-function is defined in the
# file named emacs-format-file.

if [ $# == 0 ]
then
   echo "my-indent requires at least one argument." 1>&2
   echo "Usage: my-indent files-to-indent" 1>&2
   exit 1
fi
while [ $# -ge 1 ]
do
   if [ -d $1 ]
   then
      echo "Argument of my-indent $1 cannot be a directory." 1>&2
      exit 1
   fi
   # Check for existence of file:
   ls $1 2> /dev/null | grep $1 > /dev/null
   if [ $? != 0 ]
   then
      echo "my-indent: $1 not found." 1>&2
      exit 1
   fi
   echo "Indenting $1 with emacs in batch mode"
   emacs -batch $1 -l ~/emacs/google-c-style.el -l ~/bin/emacs-format-file -f emacs-format-function
   echo
   shift 1
done
exit 0

#from http://www.cslab.pepperdine.edu/warford/BatchIndentationEmacs.html

值得注意的是Google除了C++ Style Guide, 还提供JavaScript Style Guide, Objective-C Style Guide, and Python Style Guide。对这些语言感兴趣的朋友可以到Google Style Guide发掘。

从WordPress 升级失败中恢复

今天在Wordpress里升级suffusion, 但因为VPS内存不够,升级没成功。重启VPS之后,发现如下提示“Briefly unavailable for scheduled maintenance. Check back in a minute.”,处理方法是: 删除blog/.maintenance

但诡异的问题是发现整个blog仍然无法访问,页面完全是空的(blank page,网页的source code什么也没有)。一开始认为是升级Wordpress造成了文件系统损坏,我用关键字Wordress, upgrade, suffusion, fail, blank page等等搜索了很多页面浪费了1-2个小时后,突然发现不是和升级Wordpress 过程有关,也不和wp-config.php文件的末尾有没有空行有关,而是MySQL进程没有启动!!

这里写此文来纪念失去的2个小时吧。

PS:
在这浪费的时间里发现Wordpress系统设计的很精巧:theme的安装文件和配置文件是分离开的,也就是说改变wp-content/themes/suffusion/并不影响以前的字体、颜色、版式设置……

ubuntu tree 显示中文的方法

解决方法:tree -N

正确的输出:
……
| `– 闻亭迎春-3.jpg
|– 清华大学校园风物.rar
|– 清华大学画册.pdf
|– 清华大学矢量校标.cdr
|– 清华校歌_(打印)_.doc
|– 清华校歌-校歌1.mp3
|– 清华校歌-校歌.mp3
`– 清华百年校庆标志.jpg

1 directory, 90 files

还可以用-s显示各个文件的大小:
……
| `– [ 5846622] 闻亭迎春-3.jpg
|– [ 277647851] 清华大学校园风物.rar
|– [ 10044278] 清华大学画册.pdf
|– [ 480092] 清华大学矢量校标.cdr
|– [ 98816] 清华校歌_(打印)_.doc
|– [ 1705691] 清华校歌-校歌1.mp3
|– [ 1705691] 清华校歌-校歌.mp3
`– [ 99972] 清华百年校庆标志.jpg

1 directory, 90 files

不用-N,那么tree 的默认输出是:
……
| `– \351\227\273\344\272\255\350\277\216\346\230\245-3.jpg
|– \346\270\205\345\215\216\345\244\247\345\255\246\346\240\241\345\233\255\351\243\216\347\211\251.rar
|– \346\270\205\345\215\216\345\244\247\345\255\246\347\224\273\345\206\214.pdf
|– \346\270\205\345\215\216\345\244\247\345\255\246\347\237\242\351\207\217\346\240\241\346\240\207.cdr
|– \346\270\205\345\215\216\346\240\241\346\255\214_(\346\211\223\345\215\260)_.doc
|– \346\270\205\345\215\216\346\240\241\346\255\214-\346\240\241\346\255\2141.mp3
|– \346\270\205\345\215\216\346\240\241\346\255\214-\346\240\241\346\255\214.mp3
`– \346\270\205\345\215\216\347\231\276\345\271\264\346\240\241\345\272\206\346\240\207\345\277\227.jpg

1 directory, 90 files