linuxonpower调试工具和技术.doc_第1页
linuxonpower调试工具和技术.doc_第2页
linuxonpower调试工具和技术.doc_第3页
linuxonpower调试工具和技术.doc_第4页
linuxonpower调试工具和技术.doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

linux on power 调试工具和技术https://developerworks/cn/linux/l-pow-debug/Linux on Power上的调试工具和技术文档选项未显示需要JavaScript的文档选项级别:中级2005年8月29日调试是一项主要的软件开发活动,作为应用程序开发人员,您无法避免对程序进行调试。有效的调试不仅能缩短软件开发周期,而且可以节省成本。本文简要介绍了在用户空间的C/C+和Java?应用程序中查找bug的技术,并介绍了一些可以在Linux?for POWER?架构上使用的调试技术。调试程序有很多方法,例如向屏幕上打印消息,使用调试器,或者只需仔细考虑程序如何运行,并对问题进行有根有据的猜测。在修复bug之前,首先要确定在源程序中的位置。例如,当一个程序产生崩溃或生成核心转储(core dump)时,您就需要了解是哪行代码发生了崩溃。在找到有问题的代码行之后,就可以确定这个函数中变量的值,函数是如何调用的,更具体点说,为什么会发生这种错误。使用调试器查找这些信息非常简单。本文将简要介绍几种用于修复一些很难通过可视化地检查代码而发现的bug的技术,并阐述了如何使用在Linux on Power架构上可用的工具。动态内存分配看起来似乎非常简单:您可以根据需要分配内存-使用malloc()或其变种-并在不需要时释放这些内存。实际上,内存管理的问题是软件中最为常见的bug,因为通常在程序启动时这些问题并不明显。例如,程序中的内存泄漏可能开始并不为人注意,直到经过多天甚至几个月的运行才会被发现。接下来的几节将简要介绍如何使用流行的调试器Valgrind来发现并调试这些最常见的内存bug。在开始使用任何调试工具之前,请考虑这个工具是否对重新编译应用程序有益,是否可以支持具有调试信息的库(-g选项)。如果没有启用调试信息,调试工具可以做的最好的事情也不过是猜测一段特定的代码是属于哪个函数的。这使得错误消息和概要分析输出几乎没有什么用处。使用-g选项,您就有可能获得一些信息来直接指出相关的代码行。Valgrind已经在Linux应用程序开发社区中广泛用来调试应用程序。它尤其擅长发现内存管理的问题。它可以检查程序运行时的内存泄漏问题。这个工具目前正由Julian Seward进行开发,并由Paul Mackerras移植到了Power架构上。要安装Valgrind,请从Valgrind的Web站点上下载源代码(参阅)。切换到Valgrind目录,并执行下面的命令:#make#make check#make install Valgrind的输出格式如下:#valgrind du x s.=29404=Address 0x1189AD84 is 0bytes after ablock of size 12 allocd=29404=at 0xFFB9964:malloc(vg_replace_malloc.c:130)=29404=by 0xFEE1AD0:strdup(in/lib/tls/libc.so.6)=29404=by 0xFE94D30:setlocale(in/lib/tls/libc.so.6)=29404=by 0x 10001414:main(in/usr/bin/du)=29404=是进程的ID。消息Address 0x1189AD84 is 0bytes after ablock of size 12 allocd说明在这个12字节的数组后面没有存储空间了。第二行以及后续几行说明内存是在130行(vg_replace_malloc.c)的strdup()程序中进行分配的。strdup()是在libc.so.6库的setlocale()中调用的;main()调用了setlocale()。最为常见的一个bug是程序使用了未初始化的内存。未初始化的数据可能来源于:未经初始化的变量malloc函数所分配的数据,在写入值之前使用了下面这个例子使用了一个未初始化的数组:23 int i5;4 5if(i0=0)6 i1=1;7 return 0;8在这个例子中,整数数组i5没有进行初始化;因此,i0包含的是一个随机数。因此使用i0的值来判断一个条件分支就会导致不可预期的问题。Valgrind可以很容易捕获这种错误条件。当您使用Valgrind运行这个程序时,就会接收到下面的消息:#gcc g otest1 test1.c#valgrind./test1.=31363=31363=Conditional jump or move depends on uninitialised value(s)=31363=at 0x 1000041C:main(test1.c:5)=31363=31363=ERROR SUMMARY:1 errors from 1contexts(suppressed:7 from 1)=31363=malloc/free:in use at exit:0 bytes in 0blocks.=31363=malloc/free:0 allocs,0 frees,0 bytes allocated.=31363=For counts of detected errors,rerun with:-v=31363=No mallocd blocks-no leaks are possible.Valgrind的输出说明,有一个条件分支依赖于文件test1.c中第5行中的一个未初始化的变量。内存泄漏是另外一个常见的问题,也是很多程序中最难判断的问题。内存泄漏的主要表现为:当程序连续运行时,与程序相关的内存(或堆)变得越来越大。结果是,当这个程序所消耗的内存达到系统的上限时,就会自己崩溃;或者会出现更严重的情况:挂起或导致系统崩溃。下面是一个有内存泄漏bug的示例程序:1 int main(void)23 char*p1;4 char*p2;5 6p1=(char*)malloc(512);7 p2=(char*)malloc(512);8 9p1=p2;10 11 free(p1);12 free(p2);13上面的代码分别给字符指针p1和p2分配了两个512字节的内存块,然后将指向第一个内存块的指针设置为指向第二个内存块。结果是,第二个内存块的地址丢失了,并导致内存泄漏。在使用Valgrind运行这个程序时,会返回如下的消息:#gcc g otest2 test2.c#valgrind./test2.=31468=Invalid free()/delete/delete=31468=at 0xFFB9FF0:free(vg_replace_malloc.c:152)=31468=by 0x 100004B0:main(test2.c:12)=31468=Address 0x 11899258 is 0bytes inside ablock of size 512 freed=31468=at 0xFFB9FF0:free(vg_replace_malloc.c:152)=31468=by 0x 100004A4:main(test2.c:11)=31468=31468=ERROR SUMMARY:1 errors from 1contexts(suppressed:7 from 1)=31468=malloc/free:in use at exit:512 bytes in 1blocks.=31468=malloc/free:2 allocs,2 frees,1024 bytes allocated.=31468=For counts of detected errors,rerun with:-v=31468=searching for pointers to 1not-freed blocks.=31468=checked 167936 bytes.=31468=31468=LEAK SUMMARY:=31468=definitely lost:512 bytes in 1blocks.=31468=possibly lost:0 bytes in 0blocks.=31468=still reachable:0 bytes in 0blocks.=31468=suppressed:0 bytes in 0blocks.=31468=Use-leak-ch eck=full to see details of leaked memory.正如您可以看到的一样,Valgrind报告说这个程序中有512字节的内存丢失了。这种情况发生在程序试图对一个不属于程序本身的内存地址进行读写时。在有些系统上,在发生这种错误时,程序会异常结束,并产生一个段错误。下面这个例子就是一个常见的bug,它试图读写一个超出数组边界的元素。1 int main()2 int i,*iw,*ir;3 4iw=(int*)malloc(10*sizeof(int);5 ir=(int*)malloc(10*sizeof(int);6 78 for(i=0;i 11;i+)9 iwi=i;10 11 for(i=0;i 11;i+)12 iri=iwi;13 14 free(iw);15 free(ir);16从这个程序中我们可以看出,对于iw10和ir10的访问都是非法的,因为iw和ir都只有10个元素,分别是从0到9。请注意int iw10和iw=(int*)malloc(10*sizeof(int)是等效的-它们都是用来给一个整数数组iw分配10个元素。当您使用Valgrind运行这个程序时,会返回如下的消息:#gcc g otest3 test3.c#valgrind./test3.=31522=Invalid write of size 4=31522=at 0x 100004C0:main(test3.c:9)=31522=Address 0x 11899050 is 0bytes after ablock of size 40 allocd=31522=at 0xFFB9964:malloc(vg_replace_malloc.c:130)=31522=by 0x 10000474:main(test10.c:4)=31522=31522=Invalid read of size 4=31522=at 0x 1000050C:main(test3.c:12)=31522=Address 0x 11899050 is 0bytes after ablock of size 40 allocd=31522=at 0xFFB9964:malloc(vg_replace_malloc.c:130)=31522=by 0x 10000474:main(test10.c:4)=31522=31522=ERROR SUMMARY:2 errors from 2contexts(suppressed:7 from 1)=31522=malloc/free:in use at exit:0 bytes in 0blocks.=31522=malloc/free:2 allocs,2 frees,84 bytes allocated.=31522=For counts of detected errors,rerun with:-v=31522=No mallocd blocks-no leaks are possible.在test3.c的第9行发现一个非法的4字节写操作,在第12行发现一个非法的4字节读操作。Valgrind也可以帮助判断内存误用的问题,例如:读/写已经释放的内存C+环境中错误地使用malloc/new与free/delete的配对下面这个列表介绍了POWER架构上Valgrind的状态:memcheck和addrcheck工具都可以很好地工作。然而,其他工具还没有进行大量的测试。另外,Helgrind(一个数据竞争的检测程序)在POWER上尚不能使用。所有的32位PowerPC?用户模式的指令都可以支持,除了两条非常少用的指令:lswx和stswx。具体来说,所有的浮点和Altivec(VMX)指令都可以支持。Valgrind可以在32位或64位PowerPC/Linux内核上工作,但是只能用于32位的可执行程序。有关Valgrind内存调试的更多信息,请访问Valgrind HOW TO站点。还可以参阅Steve Best的Debugging Memory Problems(Linux Magazine,2003年5月)。中有它们的链接除了Valgrind之外,还可以使用其他几个内存调试工具;例如,Memwatch和Electric Fence。除了内存bug之外,开发人员通常还会碰到程序虽然能够成功编译,但是在运行时却会产生内核转储或段错误的问题。有时在程序完成之后,程序的输出可能与所期望或设计的不同。在这两种情况中,可能代码中存在您认为正确而实际上错误的情况。接下来的几节中介绍的调试器将帮助您找到这些情况的原因。GDB(GNU项目调试器)可以让您了解程序在执行时内部究竟在干些什么,以及在程序发生崩溃的瞬间正在做什么。GDB做以下4件主要的事情来帮助您捕获程序中的bug:在程序启动之前指定一些可以影响程序行为的变量或条件在某个指定的地方或条件下暂停程序在程序停止时检查已经发生了什么在程序执行过程中修改程序中的变量或条件,这样就可以体验修复一个bug的成果,并继续了解其他bug要调试的程序可以是使用C、C+、Pascal、Objective-C以及其他很多语言编写的。GDB的二进制文件名是gdb。gdb中有很多命令。使用help命令可以列出所有的命令,以及关于如何使用这些命令的介绍。下表给出了最常用的GDB命令。命令说明例子help显示命令类别help-显示命令类别help breakpoints-显示属于breakpoints类别的命令help break-显示break命令的解释run启动所调试的程序kill终止正在调试的程序的执行通常这会在要执行的代码行已经超过了您想要调试的代码时使用。执行kill会重置断点,并从头再次运行这个程序cont所调试的程序运行到一个断点、异常或单步之后,继续执行info break显示当前的断点或观察点break在指定的行或函数处设置断点break 93 if i=8-当变量i等于8时,在第93行停止程序执行Step单步执行程序,直到它到达一个不同的源代码行。您可以使用s来代表step命令Next与step命令类似,只是它不会单步跟踪到子例程中print打印一个变量或表达式的值print pointer-打印变量指针的内容print*pointer-打印指针所指向的数据结构的内容delete删除某些断点或自动显示表达式delete 1-删除断点1。断点可以通过info break来显示watch为一个表达式设置一个观察点。当表达式的值发生变化时,这个观察点就会暂停程序的执行where打印所有堆栈帧的栈信息where-不使用参数,输出当前线程的堆栈信息where all-输出当前线程组中所有线程的堆栈信息where threadindex-输出指定线程的堆栈信息attach开始查看一个已经运行的进程attach process_id-附加到进程process_id上。process_id可以使用ps命令找到info thread显示当前正在运行的线程thread apply threadno command对一个线程运行gdb命令thread apply 3where-对线程3运行where命令Thread threadno选择一个线程作为当前线程如果一个程序崩溃了,并生成了一个core文件,您可以查看core文件来判断进程结束时的状态。使用下面的命令启动gdb:#gdb programname corefilename要调试一个core文件,您需要可执行程序、源代码文件以及core文件。要对一个core文件启动gdb,请使用-c选项:#gdb-c core programname gdb会显示是哪行代码导致这个程序产生了核心转储。默认情况下,核心转储在Novell的SUSE LINUX Enterprise Server 9(SLES 9)和Red Hat?Enterprise Linux Advanced Server(RHEL AS 4)上都是禁用的。要启用核心转储,请以root用户的身份在命令行中执行ulimit cunlimited。清单8中的例子阐述了如何使用gdb来定位程序中的bug。清单8是一段包含bug的C+代码。清单8中的C+程序试图构建10个链接在一起的数字框(number box),例如:然后试图从这个列表中逐个删除数字框。编译并运行这个程序,如下所示:#g+-g-o gdbtest1 gdbtest1.cpp#./gdbtest1 Number Box0created Number Box1created Number Box2created Number Box3created Number Box4created Number Box5created Number Box6created Number Box7created Number Box8created Number Box9created list created Number Box9deleted Segmentation fault正如您可以看到的一样,这个程序会导致段错误。调用gdb来看一下这个问题,如下所示:#gdb./gdbtest1 GNU gdb 6.2.1 Copyright 2004 Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License,and you are welcome to change it and/or distribute copies of it under certain conditions.Typeshow copyingto see the conditions.There is absolutely no warranty for GDB.Typeshow warrantyfor details.This GDB was configured asppc-suse-linux.Using host libthread_db library/lib/tls/libthread_db.so.1.(gdb)您知道段错误是在数字框9被删除之后发生的。执行run和where命令来精确定位段错误发生在程序中的什么位置。(gdb)run Starting program:/root/test/gdbtest1 Number Box0created Number Box1created Number Box2created Number Box3created Number Box4created Number Box5created Number Box6created Number Box7created Number Box8created Number Box9created list created Number Box9deleted Program received signal SIGSEGV,Segmentation fault.0x10000f74 in NumBox int:GetNext(this=0x0)at gdbtest1.cpp:14 14 NumBox T*GetNext()constreturn Next;(gdb)where#0 0x10000f74 in NumBox int:GetNext(this=0x0)at gdbtest1.cpp:14#1 0x10000d10 in NumChain int:RemoveBox(this=0x 10012008,item_to_remove=0xffffe200)at gdbtest1.cpp:63#2 0x 10000978 in main(argc=1,argv=0xffffe554)at gdbtest1.cpp:94(gdb)跟踪信息显示这个程序在第14行NumBox int:GetNext(this=0x0)接收到一个段错误。这个数字框上Next指针的地址是0x0,这对于一个数字框来说是一个无效的地址。从上面的跟踪信息可以看出,GetNext函数是由63行调用的。看一下在gdbtest1.cpp的63行附近发生了什么:54else55 temp-SetNext(current-GetNext();56 delete temp;57 temp=0;58 return 0;596061 current=0;62 temp=current;63 current=current-GetNext();6465 66 return-1;第61行current=0将这个指针设置为一个无效的地址,这正是产生段错误的根源。注释掉第61行,将其保存为gdbtest2.cpp,然后编译并重新运行。#g+-g-o gdbtest2 gdbtest2.cpp#./gdbtest2 Number Box0created Number Box1created Number Box2created Number Box3created Number Box4created Number Box5created Number Box6created Number Box7created Number Box8created Number Box9created list created Number Box9deleted Number Box0deleted这个程序现在可以成功完成而不会出现段错误了。然而,结果并不像我们预期的一样:程序在删除Number Box9之后删除了Number Box0,而不像我们期望的一样删除Number Box8,。使用gdb再次来看一下。#gdb./gdbtest2 GNU gdb 6.2.1 Copyright 2004 Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License,and you are welcome to change it and/or distribute copies of it under certain conditions.Typeshow copyingto see the conditions.There is absolutely no warranty for GDB.Typeshow warrantyfor details.This GDB was configured asppc-suse-linux.Using host libthread_db library/lib/tls/libthread_db.so.1.(gdb)break 94 if i=8 Breakpoint 1at 0x 10000968:file gdbtest2.cpp,line 94.(gdb)run Starting program:/root/test/gdbtest2 Number Box0created Number Box1created Number Box2created Number Box3created Number Box4created Number Box5created Number Box6created Number Box7created Number Box8created Number Box9created list created Number Box9deleted Breakpoint 1,main(argc=1,argv=0xffffe554)at gdbtest2.cpp:94 94 list-RemoveBox(i);您可能希望找出为什么这个程序删除的是Number Box 0,而不是Number Box 8,因此需要在您认为程序会删除Number Box 8的地方停止程序。设置这个断点:break 94 if i=8,可以在i等于8时在第94行处停止程序。然后单步跟踪到RemoveBox()函数中。(gdb)s 38 NumBox T*temp=0;(gdb)s 40 while(current!=0)(gdb)print pointer=(NumBox int*)0x 100120a8(gdb)print*pointer=Num=0,Next=0x0(gdb)指针早已指向了Number Box0,因此这个bug可能就存在于程序删除Number Box9的地方。要在gdb中重新启动这个程序,请使用kill删除原来的断点,然后添加一个i等于9时的新断点,然后再次运行这个程序。(gdb)kill Kill the program being debugged?(y or n)y(gdb)info break Num Type Disp Enb Address What 1breakpoint keep y0x 10000968 in main at gdbtest2.cpp:94 stop only if i=8 breakpoint already hit 1time(gdb)delete 1(gdb)break 94 if i=9 Breakpoint 2at 0x 10000968:file gdbtest2.cpp,line 94.(gdb)run Starting program:/root/test/gdbtest2 Number Box0created Number Box1created Number Box2created Number Box3created Number Box4created Number Box5created Number Box6created Number Box7created Number Box8created Number Box9created list created Breakpoint 2,main(argc=1,argv=0xffffe554)at gdbtest2.cpp:94 94 list-RemoveBox(i);(gdb)当这一次单步跟踪RemoveBox()函数时,要特别注意list-pointer正在指向哪一个数字框,因为bug可能就在于list-pointer开始指向Number Box0的地方。请使用display*pointer命令来查看,这会自动显示这个函数。Breakpoint 2,main(argc=1,argv=0xffffe554)at gdbtest2.cpp:94 94 list-RemoveBox(i);(gdb)s NumChain int:RemoveBox(this=0x 10012008,item_to_remove=0xffffe200)at gdbtest2.cpp:37 37 NumBox T*current=pointer;(gdb)display*pointer 1:*this-pointer=Num=9,Next=0x 10012098(gdb)s 38 NumBox T*temp=0;1:*this-pointer=Num=9,Next=0x 10012098(gdb)s 40 while(current!=0)1:*this-pointer=Num=9,Next=0x 10012098(gdb)s 41 if(current-GetValue()=item_to_remove)1:*this-pointer=Num=9,Next=0x 10012098(gdb)s NumBox int:GetValue(this=0x 100120a8)at gdbtest2.cpp:16 16 const T&GetValue()constreturn Num;(gdb)s NumChain int:RemoveBox(this=0x 10012008,item_to_remove=0xffffe200)at gdbtest2.cpp:42 42 if(temp=0)1:*this-pointer=Num=9,Next=0x 10012098(gdb)s 44 if(current-GetNext()=0)1:*this-pointer=Num=9,Next=0x 10012098(gdb)s NumBox int:GetNext(this=0x 100120a8)at gdbtest2.cpp:14 14 NumBox T*GetNext()constreturn Next;(gdb)s NumChain int:RemoveBox(this=0x 10012008,item_to_remove=0xffffe200)at gdbtest2.cpp:50 50 delete current;1:*this-pointer=Num=9,Next=0x 10012098(gdb)sNumBox(this=0x 100120a8)at gdbtest2.cpp:10 10 std:coutNumber BoxGetValue()deletedstd:endl;(gdb)s NumBox int:GetValue(this=0x 100120a8)at gdbtest2.cpp:16 16 const T&GetValue()constreturn Num;(gdb)s Number Box9deletedNumBox(this=0x 100120a8)at gdbtest2.cpp:11 11 Next=0;(gdb)s NumChain int:RemoveBox(this=0x 10012008,item_to_remove=0xffffe200)at gdbtest2.cpp:51 51 current=0;1:*this-pointer=Num=0,Next=0x0(gdb)s 53 return 0;1:*this-pointer=Num=0,Next=0x0(gdb)s 0x10000d1c 66 return-1;1:*this-pointer=Num=0,Next=0x0从上面的跟踪过程中,您可以看到list-pointer在删除Number Box9之后指向了Number Box0。这个逻辑并不正确,因为在删除Number Box9之后,list-pointer应该指向的是Number Box8。现在非常显然我们应该在第50行之前添加一条语句pointer=pointer-GetNext();,如下所示:49else50 pointer=pointer-GetNext();51 delete current;52 current=0;5354 return 0;将新修改之后的程序保存为gdbtest3.cpp,然后编译并再次运行。#g+-g-o gdbtest3 gdbtest3.cpp#./gdbtest3 Number Box0created Number Box1created Number Box2created Number Box3created Number Box4created Number Box5created Number Box6created Number Box7created Number Box8created Number Box9created list created Number Box9deleted Number Box8deleted Number Box7deleted Number Box6deleted Number Box5deleted Number Box4deleted Number Box3deleted Number Box2deleted Number Box1deleted Number Box0deleted这才是我们期望的结果。在GDB中有一些特殊的命令可以用于多线程应用程序的调试。下面这个例子给出了一个死锁情况,并介绍了如何使用这些命令来检查多线程应用程序中的问题:#include stdio.h#includepthread.h pthread_mutex_t AccountA_mutex;pthread_mutex_t AccountB_mutex;struct BankAccountchar account_name1;int balance;struct BankAccount accountA=A,10000;struct BankAccount accountB=B,20000;void*transferAB(void*amount_ptr)int amount=*(int*)amount_ptr);pthread_mutex_lock(&AccountA_mutex);if(accountA.balance amount)printf(There is not enough memory in Account A!n);pthread_mutex_unlock(&AccountA_mutex);pthread_exit(void*)1);accountA.balance-=amount;sleep(1);pthread_mutex_lock(&AccountB_mutex);accountB.balance+=amount;pthread_mutex_unlock(&AccountA_mutex);pthread_mutex_unlock(&AccountB_mutex);void*transferBA(void*amount_ptr)int amount=*(int*)amount_ptr);pthread_mutex_lock(&AccountB_mutex);if(accountB.balance amount)printf(There is not enough memory in Account B!n);pthread_mutex_unlock(&AccountB_mutex);pthread_exit(void*)1);accountB.balance-=amount;sleep(1);pthread_mutex_lock(&AccountA_mutex);accountA.balance+=amount;pthread_mutex_unlock(&AccountB_mutex);pthread_mutex_unlock(&AccountA_mutex);int main(int argc,char*argv)int threadid4;pthread_t pthread4;int transfer_amount4=100,200,300,400;int final_balanceA,final_balanceB;final_balanceA=accountA.balance-transfer_amount0-transfer_amount1+transfer_amount2+transfer_amount3;final_balanceB=accountB.balance+transfer_amount0+transfer_amount1-transfer_amount2-transfer_amount3;if(threadid0=pthread_create(&pthread0,NULL,transferAB,(void*)&transfer_amount0)0)perror(Thread#0 creation failed.);exit(1);if(threadid1=pthread_create(&pthread1,NULL,transferAB,(void*)&transfer_amount1)0)perror(Thread#1 creation failed.);exit(1);if(threadid2=pthread_create(&pthread2,NULL,transferBA,(void*)&transfer_amount2)0)perror(Thread#2 creation failed.);exit(1);if(threadid3=pthread_create(&pthread3,NULL,transferBA,(void*)&transfer_amount3)0)perror(Thread#3 creation failed.);exit(1);printf(Transitions are in progress.);while(accountA.balance!=final_balanceA)&(accountB.balance!=final_balanceB)printf(.);printf(nAll the money is transferred!n);使用gcc来编译这个程序,如下所示:#gcc-g-o gdbtest2 gdbtest2.c-L/lib/tls-lpthread程序gdbtest2会挂起,不会返回一条All the money is transferred!消息。将gdb附加到正在运行的进程上,从而了解这个进程内部正在发生什么。#ps-ef|grep gdbtest2 root 9510 8065 106:30 pts/1 00:00:00./gdbtest2 root 9516 9400 006:30 pts/4 00:00:00 grep gdbtest2#gdb-pid 9510 GNU gdb 6.2.1 Copyright 2004 Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License,and you are welcome to change it and/or distribute copies of it under certain conditions.Typeshow copyingto see the conditions.There is absolutely no warranty for GDB.Typeshow warrantyfor details.This GDB was configured asppc-suse-linux.Attaching to process 9510 Reading symbols from/root/test/gdbtest2.done.Using host libthread_db library/lib/tls/libthread_db.so.1.Reading symbols from/lib/tls/libpthread.so.0.done.Thread debugging using libthread_db enabledNew Thread 1073991712(LWP 9510)New Thread 1090771744(LWP 9514)New Thread 1086577440(LWP 9513)New Thread 1082383136(LWP 9512)New Thread 1078188832(LWP 9511)Loaded symbols for/lib/tls/libpthread.so.0 Reading symbols from/lib/t ls/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论