函数调用栈的获取原理分析

上一篇文章《在Linux程序中输出函数调用栈》,讲述了在Linux中如何利用backtrace获取调用栈,本篇文章主要介绍一下获取函数调用栈的原理,并给出相应的实现方式。

要了解调用栈,首先需要了解函数的调用过程,下面用一段代码作为例子:

#include <stdio.h>

int add(int a, int b) {
    int result = 0;

    result = a + b;

    return result;
}

int main(int argc, char *argv[]) {
    int result = 0;

    result = add(1, 2);

    printf("result = %d \r\n", result);

    return 0;
}

使用gcc编译,然后gdb反汇编main函数,看看它是如何调用add函数的:

(gdb …

在Linux程序中输出函数调用栈

程序发生异常时,将函数的调用栈打印出来,可以大大提高定位效率。

Linux中提供了三个函数用来获取调用栈:

/* 获取函数调用栈 */
int backtrace(void **buffer, int size);

/* 将调用栈中的函数地址转化为函数名称 并返回一个字符串数组 */
char **backtrace_symbols(void *const *buffer, int size);

/* 将调用栈中的函数地址转化为函数名称 并将其定入到文件中 */
void backtrace_symbols_fd(void *const *buffer, int size, int fd);

示例代码:

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* 打印调用栈的最大深度 */
#define DUMP_STACK_DEPTH_MAX 16

/* 打印调用栈函数 */
void dump_trace() {
    void *stack_trace …



终端下使用代理的方法

很长时间都不知道怎么设置,今天突然发现,设置四个环境变量就行了,"HTTP_PROXY"、"http_proxy"和"FTP_PROXY"、"ftp_proxy",在"~/.bash_profile"中添加以下几行:

export HTTP_PROXY=http://username:password@proxy.server:8080
export FTP_PROXY=http://username:password@proxy.server:8080
export http_proxy=http://username:password@proxy.server:8080
export ftp_proxy=http://username:password@proxy.server:8080

其中,username和password是用户名和密码,用在需要验证的代理服务器上;proxy.server是代理服务器的地址,后面的8080是端口号。

修改保存后重启终端或在执行 …


Fedora 9 无法启动KDE的解决办法

今天突然想再尝试一下KDE的环境,而且传说中的KDE4出了那么久,还一直没有用过,于是兴致勃勃的安装上了KDE的桌面环境。Logout->KDE,结果却报出个错误,说"Could not start kstartupconfig4. Check your installation",无语,难道是我少装了什么东西?

按照它说的检查,结果没问题啊,kstartupconfig4已经安装好了,于是又上网查,google出好多解决办法,不过基本上都是用"chown"改变"~/.kde"目录的所有者,哦?检查……"~/.kde"这个目录竟然是root的,原来是权限的问题。

输入"chown -R owner ~/.kde",为了保险,再加个"chgrp -R group ~/.kde",这里面的"owner"和"group"分别是当前的用户名和用户所在的组名。

之后重新进入KDE,一切正常 …


Linux下将.cue/.bin转换为.iso的方法

从学校的FTP上下了个Windows 2000 Advance Server光盘镜像,打算装在虚拟机里,结果发现下下来的镜像是.cue/.bin格式的,VirtualBox还用不了,于是跑google上搜了一大堆linux里转换.iso格式的软件,发现一个叫"bchunk"的小软件非常好用,而且小的可以,才几十K,很不错。

在终端里输入如下命令:

bchunk e-w2sp4ru1as.bin e-w2sp4ru1as.cue e-w2sp4ru1as.iso

其中,e-w2sp4ru1as.e-w2sp4ru1as.cue是原来的镜像名,e-w2sp4ru1as.iso是转换后想要保存的文件名。

等一小会儿,就像下面这幅图一样,会有一个进度条,进度到100%后转换就完成了。 Convert CUE and BIN to ISO format


新版VirtualBox在Fedora下不能启动虚拟机的解决办法

前一段时间突然发现VirtualBox被Sun收购了,改名成"Sun xVM VirtualBox",于是兴致勃勃的安上了最新版,结果发现虚拟机启动不了了,提示错误:

VirtualBox kernel driver not installed. The vboxdrv kernel module was either not loaded or /dev/vboxdrv was not created for some reason. 
Re-setup the kernel module by executing ‘/etc/init.d/vboxdrv setup’ as root.

于是按照提示在终端里执行"sudo /etc/init.d/vboxdrv setup …


因字符编码导致的编译不通过

从网上下了QR标准的二维码库,打算直接调用里面的类来实现。在Fedora下Java编译通过,只是提示了一下使用了过时的方法。但我把代码复制到Windows里时,却编译不同过,出现了近1k个错误,代码完全一样,只是操作系统不同就会出问题?

回想在Windows里用UltraEdit打开时,提示文件不是"DOS Format",会不会和文字编码有关?Linux用的是UTF-8的编码,而Windows用的是GBK的编码,难道字符编码必须要和本地相同才能编译通过么?试一下,于是把代码用UltraEdit转换成了GBK编码,再次编译,终于正常通过。

看来有时编译不通过不一定是语句问题,连文件的编码也有可能出问题,如果在不同系统中出现类似上面一个正常一个错误的情况,可以考虑看是不是因为文件的编码和系统默认的编码有差异而引起的。


Fedora禁止自动挂载分区的方法

Fedora在启动时会自动把系统中的其它分区挂载,为了对自动挂载的分区进行一定的限制,就要改变相应的策略,这一策略存放在"/usr/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi"文件中。

找到以下提示行

<!-- Here follow volumes we specifically want to ignore - it is the -->
<!-- responsibility of software higher in the stack (e.g. gnome-vfs) -->
<!-- amd mount programs (e.g. Mount() on HAL) to respect volume.ignore -->
<merge key="volume …