![[ 永远的UNIX::UNIX技术资料的宝库 ]](/images/title.gif)
|
| 首页 > 编程技术 > C/C++ > 正文 |
 |
| Solaris2.4 多线程编程指南6--编译和调试 |
| 本文出自:BBS水木清华站 作者:Mccartney (coolcat) (2002-01-29 20:32:52) |
6 编译和调试 本章描述了怎样编译和调试多线程程序。 编译一个多线程应用程序 调试一个多线程应用程序 6.1编译一个多线程应用程序 6.1.1使用C编译器 确认你拥有如下软件,否则将无法正常编译和连接多线程程序 · 头文件:thread.h errno.h · 标准C编译器 · 标准Solaris连接器 · 线程库(libthread) · MT-Safe库(libc, libm, libw, libintl, libmalloc, libmapmalloc, libnsl, 等等) 6.1.2用替代(_REENTRANT)标志进行编译 在编译多线程程序时使用"-D _REENTRANT"标志。 这个标志必须在编译应用程序的每一个模块时都使用。如果没有这个标志,将使用errno, stdio等等的旧的定义。如果要编译一个单线程应用程序,不要使用这个标志。 *新旧连接需要小心 表6-1显示了多线程目标代码模块与旧的代码模块连接时需要非常慎重。 表6-1 在编译多线程程序时使用"-D _REENTRANT"标志 文件类型 编译 参考 返回 旧的目标文件(非线程版)和新的目标文件 没有 "-D _REENTRANT" 标志。 静态储存 传统的errno 新的目标文件 有 "-D _REENTRANT"标志。 __errno,新的二进制入口 线程定义errno的地址 用libnsl 里的TLI编程 有 "-D _REENTRANT"标志(必须)。 __t_errno,一个新的入口 线程定义t_errno的地址 6.1.3使用libthread 为了在连接时使用libthread,需要在ld命令行里,-lc参数之前,指定 -lthread,或者在cc 命令行的最后指定。 如果应用程序没有连接libthread,则对该库中的函数调用不产生实际操作。 Libc定义libthread为空过程。???真正的过程是在应用程序既连接libc也 连接libthread时由libthread加入的。 如果一个ld命令行包含了以下的字段:.o's ... -lc -lthread ...,则C函数库的行为没有被定义。??? 不要在单线程程序中使用-lthread。这样做将在连接时建立多线程机制,在运 行时将被初始化。这样做不但浪费资源,而且在调试中会对运行结果有不正确的显示。 6.1.4使用非C的编译器 线程库使用libc中的如下内容: · 系统调用包装器(system call wrappers) · 用来显示出错信息的调用(通常是printf) · 运行时的连接支持来解析符号(因为库是动态连接的) 你也可以写自己的系统调用包装器和自己的printf函数,并且在连接时(而不 是在运行时)进行符号解析,这样可以消除对libc的依赖。 如果线程使用应用程序提供的堆栈,则线程库不使用动态分配内存的办法。 Thr_create(3T)函数可以由应用程序指定自己的堆栈。 6.2调试多线程应用程序 6.2.1一般的疏漏 以下列出可以导致多线程出错的常见疏漏: · 给新线程传递参数时使用局部或全局变量 · 在没有同步机制的保护下访问全局内存 · 两个线程以不同的顺序去申请两个资源导致死锁(两个线程各自占有一个资源并相执不下) · 在同步保护中有隐藏的漏洞。例如可能有如下情况:一个有同步机制(例如互斥 锁)保护的代码段包含一个先释放再重新获得同步机制的函数调用,结果是全局内存 实际上没有得到保护。 · 有隐匿的,重复或递归的大自动数组的使用可能导致问题,因为多线程程序的堆 栈容量比单线程程序有更多的限制。 · 指定的堆栈空间不够。 · 没有通过线程库的调用指定堆栈。 注意,多线程程序(特别是有错误的)经常在相同输入的情况下得到不同的结 果,因为线程调度的顺序不同。 一般的,多线程bug具有统计性,而不是确定性。在调试时,跟踪的办法将会比 设断点的办法好些。 6.2.2使用adb 如果你在一个多线程程序当中绑定所有线程,一个线程和一个LWP是同步的。然 后你通过如下支持多线程编程的adb命令访问每一个线程。 表6-2 MT adb命令 ------------------------------------- pid:A 绑定在进程pid上,这将停止进程及其所有LWP ∶R 与进程分离,这将恢复进程及其所有LWP $L 显示在(停止的)进程中所有的活动的LWP n:l 将焦点切换到第n号LWP $l 显示当前焦点所在的LWP num:i 忽略信号码为num的信号 6.2.3使用dbx 使用dbx,可以调试和执行用C++, ANSI C, FORTRAN和PASCAL的源程序。Dbx使用与SPARCworks? Debugger相同的命令,但使用标准终端(tty)接口。Dbx和 SPARCworks Debugger现在都支持多线程程序。 要得到dbx和Debugger的全面认识,请参考SunPro dbx(1) man page和 《Debugging a Program》用户指南。 以下的dbx选项支持多线程。 表6-3 给MT程序使用的dbx选项 Cont at line[sig signo id] 在信号signo发生时继续执行第line行。 参见dbx的命令语言的循环控制里的continue。 如果有id参数,则指定继续哪一个线程或LWP。 缺省设置为all。 Lwp 显示当前LWP。切换到给定LWP[lwpid] Lwps 列出当前进程的所有LWP Next … tid 单步执行指定线程。如果一个函数调用被跳过, 所有的LWP在该函数调用期间重新开始???非 活动线程不能被单步执行 Next … lid 单步执行指定LWP。在跳过函数时并不隐含地恢 复所有的LWP。在该LWP上的线程是活动的。 Step … tid 单步执行指定线程。如果一个函数调用被跳过, 所有的LWP在该函数调用期间重新开始???非 活动线程不能被单步执行 Step … lid 单步执行指定LWP。在跳过函数时并不隐含地恢 复所有的LWP。 Stepi … lid 指定的LWP Stepi … tid 在LWP上的线程是活动的。 Thread 显示当前线程。切换到线程tid。在以下情况中, 一个可选的tid指当前线程。 Thread -info[tid] 打印指定线程的所有已知情况。 Thread -locks[tid] 打印被指定线程控制的所有锁 Thread -suspend[tid] 把指定线程置于挂起状态。 Thread -continue[tid] 使指定线程退出挂起状态。 Thread -hide[tid] 隐藏指定(或当前)线程,在普通线程列表中 将不被显示出来 Thread -unhide [tid] 解除指定线程的隐藏状态 Allthread-unhide 解除所有线程的隐藏状态 Threads 打印已知线程的列表 Threads-all 打印所有线程(包括通常不被打印的,zombies) All|filterthreads-mode 控制threads命令打印所有线程还是有选择地列表 Auto|manualthreads-mode 使在GUI界面里线程监控器(Thread Inspector) 线程列表得以自动更新 Threads -mode 显示当前模式。Any of the previous forms can be followed by a thread or LWP ID to get the traceback for the specified entity.
(http://www.fanqiang.com)
进入【UNIX论坛】
|
|
| 相关文章 |
Solaris2.4 多线程编程指南7--编程指南 (2002-01-29 20:33:46) Solaris2.4 多线程编程指南6--编译和调试 (2002-01-29 20:32:52) Solaris2.4 多线程编程指南5--安全和不安全的接口函数 (2002-01-29 20:32:05) Solaris2.4 多线程编程指南4--操作系统编程 (2002-01-29 20:29:36) Solaris2.4 多线程编程指南3--使用同步对象编程 (2002-01-29 20:28:07) Solaris2.4 多线程编程指南2--用多线程编程 (2002-01-29 20:26:32) Solaris2.4 多线程编程指南1--线程基础 (2002-01-29 20:25:25) Linux下的多线程编程 (2001-08-11 09:05:00)
|
|
|
|
 |
★ 樊强制作 欢迎分享 ★ |