EDU511 国际专业IT教育服务门户
设为首页   加入收藏    联系我们
寻找IT教育内容合作伙伴
招聘教育网络编辑和运营门户高手
中讯IT教育2008年改版上线
寻找地方站运营伙伴QQ:59955917
中讯IT 技术成就未来
   你现在的位置:首页 >> 新闻系统 >> 操作系统 >> Unix >> 高级教程 >> 正文

Unix编程/应用问答中文版 ---2.堆栈相关问题

 
 
日期:08-06-02 22:44:11 点击: 来源:中讯IT
 
2. 堆栈相关问题
2.1 如何理解pstack的输出信息
2.2
2.3 Solaris中如何获取一个C程序的调用栈回溯
2.4 如何编程获取栈底地址
2.5 如何得到一个运行中进程的内存映像
2.6 调试器如何工作的
2.7 x86/Linux上如何处理SIGFPE信号
--------------------------------------------------------------------------
2. 堆栈相关问题

2.1 如何理解pstack的输出信息

Q: 080603a7 main (1, 80479b8, 80479c0) + d53
结尾的d53是什么

A: Roger A. Faulkner <raf@sunraf.Sun.COM>

在代码段绝对地址0x080603a7处,main()调用了一个函数,0x080603a7正是
main + 0xd53,换句话说,从main()函数开始的0xd53偏移处。

2.3 Solaris中如何获取一个C程序的调用栈回溯

Q: 我想在Solaris 2.6极其后续版本上获取一个C程序的调用栈回溯,类似如下输出

(10) 0x00045e08 integ + 0x408 [./two_brn.e]
(11) 0x0006468c trajcem + 0x128 [./two_brn.e]
(12) 0x00055490 fly_traj + 0xf58 [./two_brn.e]
(13) 0x0004052c top_level + 0x14 [./two_brn.e]
(14) 0x000567e4 _start + 0x34 [./two_brn.e]

这样我就可以知道当程序崩溃、死锁的时候代码执行到了何处。在HP-UX和IRIX上
可以利用U_STACK_TRACE()和trace_back_stack_and_print(),Solaris上呢?

Q: 有没有办法显示当前堆栈中的数据(GNU/Linux系统)?我希望自己的异常处理程序
在进程结束前dump整个栈区(stack),以便观察到栈顶是什么函数。对于调试意想
不到的运行时错误而言,这很重要。

A: Bjorn Reese <breese@mail1.stofanet.dk>

用/usr/proc/bin/pstack [-F] <pid ...>

参看这个例子代码,http://home1.stofanet.dk/breese/debug/debug.tar.gz

Q: is there a way to access call stack information at run time from within
a program? i've been maintaining my own crude stack using __FUNCTION__
and linked lists but can't help but think there's gotta be a better
way...

A: Nate Eldredge <neldredge@hmc.edu>

这依赖于你的系统,如果使用glibc 2.1或更新版本,可以使用backtrace()函数,
参看<execinfo.h>,其他系统可能有不同的技术支持。

注意,你所使用的办法可能是唯一能够保证跨平台使用的

A: Andrew Gabriel <andrew@cucumber.demon.co.uk> Consultant Software Engineer

下面是一个backtrace()的应用举例,如果你使用Solaris 2.4及其后续版本,那
么这个例子可以很好的工作。很可能无法工作在64-bit模式下,我没有尝试过,
好像Solaris 7已经提供了一个类似的演示程序。还可以增加某些功能,我没有时
间了。

/*
* Produce a stack trace for Solaris systems.
*
* Copyright (C) 1995-1998 Andrew Gabriel <andrew@cucumber.demon.co.uk>
* Parts derived from Usenet postings of Bart Smaalders and Casper Dik.
*
*/

/* ......................................................................... */

#include <setjmp.h>
#include <sys/types.h>
#include <sys/reg.h>
#include <sys/frame.h>
#include <dlfcn.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>

#if defined(sparc) || defined(__sparc)
#define FLUSHWIN() asm("ta 3");
#define FRAME_PTR_INDEX 1
#define SKIP_FRAMES 0
#endif

#if defined(i386) || defined(__i386)
#define FLUSHWIN()
#define FRAME_PTR_INDEX 3
#define SKIP_FRAMES 1
#endif

#if defined(ppc) || defined(__ppc)
#define FLUSHWIN()
#define FRAME_PTR_INDEX 0
#define SKIP_FRAMES 2
#endif

/* ......................................................................... */

static void print_address ( void * pc )
{
Dl_info info;

if ( dladdr( pc, &info ) == 0 )
{
/* not found */
fprintf( stderr, "*** %s:0x%x\n", "??", ( unsigned int )pc );
}
else
{
/* found */
fprintf( stderr, "*** %s:%s+0x%x\n", info.dli_fname, info.dli_sname,
( unsigned int )pc - ( unsigned int )info.dli_saddr );
}
return;
} /* end of print_address */

/* ......................................................................... */

static int validaddr ( void * addr )
{
static long pagemask = -1;
char c;

if ( pagemask == -1 )
{
pagemask = ~( sysconf( _SC_PAGESIZE ) - 1 );
}
addr = ( void * )( ( long )addr & pagemask );
if ( mincore( ( char * )addr, 1, &c ) == -1 && errno == ENOMEM )
{
return 0; /* invalid */
}
else
{
return 1; /* valid */
}
} /* end of validaddr */

/* ......................................................................... */

/*
* this function walks up call stack, calling print_addess
* once for each stack frame, passing the pc as the argument.
*/

static void print_stack ( void )
{
struct frame * sp;
jmp_buf env;
int i;
int * iptr;

FLUSHWIN();

setjmp( env );
iptr = ( int * )env;

sp = ( struct frame * )iptr[ FRAME_PTR_INDEX ];

for ( i = 0; i < SKIP_FRAMES && sp; i++ )
{
if ( !validaddr( sp ) || !validaddr( &sp->fr_savpc ) )
{
fprintf( stderr, "***[stack pointer corrupt]\n" );
return;
}
sp = ( struct frame * )sp->fr_savfp;
}

i = 100; /* looping check */

while ( validaddr( sp ) && validaddr( &sp->fr_savpc ) && sp->fr_savpc && --i
)
{
print_address( ( void * )sp->fr_savpc );
sp = ( struct frame * )sp->fr_savfp;
}
} /* end of print_stack */

/* ......................................................................... */

void backtrace( void )
{
fprintf( stderr, "***backtrace...\n" );
print_stack();
fprintf( stderr, "***backtrace ends\n" );
}

/* ......................................................................... */

2.4 如何编程获取栈底地址

Q: 虽然很多操作系统的用户进程栈底地址固定,但是我需要写一个可广泛移植C程序
获取这个栈底地址。

A: tt <warning3@nsfocus.com> 2001-06-02 19:40

假设堆栈(stack)向低地址方向增长,则所谓栈底指堆栈(stack)最高地址

x86/Linux 栈底是0xc0000000( 栈底往低地址的4个字节总是零 )
SPARC/Solaris 7/8 栈底是0xffbf0000( 栈底往低地址的4个字节总是零 )
SPARC/Solaris 2.6 栈底是0xf0000000( 栈底往低地址的4个字节总是零 )
x86/FreeBSD 栈底是0xbfc00000( 栈底往低地址的4个字节总是零 )
x86/NetBSD 1.5 栈底是0xbfbfe000
x86/OpenBSD 2.8 栈底是0xdfbfe000

D: jonah

对于NetBSD 1.5,栈底是0xbfc00000。根据源码,最高用户地址是0xbfbfe000,因为
最后4MB(2^22)的最后两页(0x2000字节,一页4096字节)保留用做U区,但是目前不再
使用这块内存。因此,0xbfbfe000才是真正的栈底。

tt在OpenBSD 2.8上测试结果,栈底是0xdfbfe000,注意和NetBSD 1.5相差很大。

A: tt <warning3@nsfocus.com>

--------------------------------------------------------------------------
/*
* gcc -Wall -O3 -o gstack gstack.c
*
* A simple example to get the current stack bottom address
* warning3 <warning3@nsfocus.com>
* 2001-06-01
*
* Modified by scz <scz@nsfocus.com>
* 2001-06-02
*/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>

typedef void Sigfunc ( int ); /* for signal handlers */

Sigfunc * signal ( int signo, Sigfunc * func );
static Sigfunc * Signal ( int signo, Sigfunc * func );
static char * get_stack_bottom ( void );
static void segfault ( int signo );

static sigjmp_buf jmpbuf;
static vol
 
责任编辑:
 
前一篇:
后一篇:
相关新闻(文章)

登录模块加载中...
热点操作系统技术
友情链接
重庆之窗 | 重庆IT教育 | 我爱论文网 | 涪陵课件园 | 中国教育导航 | 第一教育网 | 中华IT培训网 
百度网址大全   重庆电脑维修网   华育国际教育 maple story   中国销售培训网    更多友情链接>>>
地址:重庆渝中区大坪正街88号 Copyright © edu511.com All rights reserved.
本站建设得到北京泰胜得风险投资机构、重庆网通信息港、平全教育服务中心与的大力支持            重庆视网科技发展有限公司版权所有 邮编:400041
电话:023-61630611 15902314551            ICP备案号:渝ICP备08002346号 QQ:59955917       邮箱:sysium_yuh@126.com yuhong@edu511.com