gdb调试命令----小话c语言(15)

来源:互联网 发布:js强制转换成数字 编辑:程序博客网 时间:2024/06/03 22:44

[Mac-10.7.1  Lion  Intel-based  x64  gcc4.2.1  GNU gdb 6.3.50-20050815 (Apple version gdb-1708)]


Q: 给个简单的代码,然后进入调试状态。

A: 如下代码,保存为hello.c:

#include <stdio.h>int main(){    int i = 2;    printf("%d\n", i);    return 0;}
gcc编译,需要有-g参数:gcc  -g  hello.c  -o  hello得到带调试信息的hello可执行文件,gdb  hello进入调试状态,输入list查看源代码信息:

可以看到hello.c源代码被打印出来了。输入run命令运行程序,

可以看到程序开始运行,且输出了结果。


Q: 如何能够看到调试信息?

A: 可以通过源代码编译后的汇编代码得到信息。gcc  -S  -g  hello.c得到hello.s文件:

.section__TEXT,__text,regular,pure_instructions.section__DWARF,__debug_frame,regular,debugLsection_debug_frame:.section__DWARF,__debug_info,regular,debugLsection_info:.section__DWARF,__debug_abbrev,regular,debugLsection_abbrev:.section__DWARF,__debug_aranges,regular,debugLsection_aranges:.section__DWARF,__debug_macinfo,regular,debugLsection_macinfo:Lsection_line:.section__DWARF,__debug_loc,regular,debugLsection_loc:.section__DWARF,__debug_pubnames,regular,debugLsection_pubnames:.section__DWARF,__debug_pubtypes,regular,debugLsection_pubtypes:.section__DWARF,__debug_str,regular,debugLsection_str:.section__DWARF,__debug_ranges,regular,debugLsection_ranges:.section__TEXT,__text,regular,pure_instructionsLtext_begin:.section__DATA,__dataLdata_begin:.section__TEXT,__text,regular,pure_instructions.globl_main.align4, 0x90_main:Leh_func_begin1:Lfunc_begin1:Ltmp3:pushq%rbpLtmp0:movq%rsp, %rbpLtmp1:Ltmp4:subq$16, %rspLtmp2:movl$2, -12(%rbp)Ltmp5:movl-12(%rbp), %eaxxorb%cl, %clleaqL_.str(%rip), %rdxmovq%rdx, %rdimovl%eax, %esimovb%cl, %alcallq_printfLtmp6:movl$0, -8(%rbp)movl-8(%rbp), %eaxmovl%eax, -4(%rbp)movl-4(%rbp), %eaxaddq$16, %rsppopq%rbpretLtmp7:Lfunc_end1:Leh_func_end1:.section__TEXT,__cstring,cstring_literalsL_.str:.asciz "%d\n".section__TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_supportEH_frame0:Lsection_eh_frame:Leh_frame_common:Lset0 = Leh_frame_common_end-Leh_frame_common_begin.longLset0Leh_frame_common_begin:.long0.byte1.asciz "zR".byte1.byte120.byte16.byte1.byte16.byte12.byte7.byte8.byte144.byte1.align3Leh_frame_common_end:.globl_main.eh_main.eh:Lset1 = Leh_frame_end1-Leh_frame_begin1.longLset1Leh_frame_begin1:Lset2 = Leh_frame_begin1-Leh_frame_common.longLset2Ltmp8:.quadLeh_func_begin1-Ltmp8Lset3 = Leh_func_end1-Leh_func_begin1.quadLset3.byte0.byte4Lset4 = Ltmp0-Leh_func_begin1.longLset4.byte14.byte16.byte134.byte2.byte4Lset5 = Ltmp1-Ltmp0.longLset5.byte13.byte6.align3Leh_frame_end1:.section__TEXT,__text,regular,pure_instructionsLtext_end:.section__DATA,__dataLdata_end:.section__TEXT,__text,regular,pure_instructionsLsection_end1:.section__DWARF,__debug_frame,regular,debugLdebug_frame_common:Lset6 = Ldebug_frame_common_end-Ldebug_frame_common_begin.longLset6Ldebug_frame_common_begin:.long4294967295.byte1.byte0.byte1.byte120.byte16.byte12.byte7.byte8.byte144.byte1.align2Ldebug_frame_common_end:Lset7 = Ldebug_frame_end1-Ldebug_frame_begin1.longLset7Ldebug_frame_begin1:Lset8 = Ldebug_frame_common-Lsection_debug_frame.longLset8.quadLfunc_begin1Lset9 = Lfunc_end1-Lfunc_begin1.quadLset9.byte4Lset10 = Ltmp0-Lfunc_begin1.longLset10.byte14.byte16.byte134.byte2.byte4Lset11 = Ltmp1-Ltmp0.longLset11.byte13.byte6.align2Ldebug_frame_end1:.section__DWARF,__debug_info,regular,debugLinfo_begin1:.long201.short2Lset12 = Labbrev_begin-Lsection_abbrev.longLset12.byte8.byte1.ascii "4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)".byte0.byte1.ascii "hello.c".byte0.quad0.long0.ascii "/Users/xichen/codes/c_simple/".byte0.byte2.byte5.ascii "int".byte0.byte4.byte3.ascii "main".byte0.ascii "main".byte0.byte1.byte4.byte1.long125.byte1.quadLfunc_begin1.quadLfunc_end1.byte1.byte86.byte4.quadLtmp4.quadLtmp7.byte5.byte105.byte0.byte1.byte5.long125.byte2.byte145.byte116.byte0.byte0.byte0.byte0.byte0.byte0.byte0Linfo_end1:.section__DWARF,__debug_abbrev,regular,debugLabbrev_begin:.byte1.byte17.byte1.byte37.byte8.byte19.byte11.byte3.byte8.byte82.byte1.byte16.byte6.byte27.byte8.byte0.byte0.byte2.byte36.byte0.byte62.byte11.byte3.byte8.byte11.byte11.byte0.byte0.byte3.byte46.byte1.byte3.byte8.byte135.byte64.byte8.byte58.byte11.byte59.byte11.byte39.byte12.byte73.byte19.byte63.byte12.byte17.byte1.byte18.byte1.byte64.byte10.byte0.byte0.byte4.byte11.byte1.byte17.byte1.byte18.byte1.byte0.byte0.byte5.byte52.byte0.byte3.byte8.byte58.byte11.byte59.byte11.byte73.byte19.byte2.byte10.byte0.byte0.byte0Labbrev_end:.section__DWARF,__debug_line,regular,debugLset13 = Lline_end-Lline_begin.longLset13Lline_begin:.short2Lset14 = Lline_prolog_end-Lline_prolog_begin.longLset14Lline_prolog_begin:.byte1.byte1.byte246.byte245.byte10.byte0.byte1.byte1.byte1.byte1.byte0.byte0.byte0.byte1.asciz "/Users/xichen/codes/c_simple/".byte0.asciz "hello.c".byte1.byte0.byte0.byte0Lline_prolog_end:.byte0.byte9.byte2.quadLtmp3.byte23.byte0.byte9.byte2.quadLtmp4.byte21.byte0.byte9.byte2.quadLtmp5.byte21.byte0.byte9.byte2.quadLtmp6.byte21.byte0.byte9.byte2.quadLsection_end1.byte0.byte1.byte1Lline_end:.section__DWARF,__debug_pubnames,regular,debugLset15 = Lpubnames_end1-Lpubnames_begin1.longLset15Lpubnames_begin1:.short2Lset16 = Linfo_begin1-Lsection_info.longLset16Lset17 = Linfo_end1-Linfo_begin1.longLset17.long132.asciz "main".long0Lpubnames_end1:.section__DWARF,__debug_pubtypes,regular,debugLset18 = Lpubtypes_end1-Lpubtypes_begin1.longLset18Lpubtypes_begin1:.short2Lset19 = Linfo_begin1-Lsection_info.longLset19Lset20 = Linfo_end1-Linfo_begin1.longLset20.long0Lpubtypes_end1:.section__DWARF,__debug_aranges,regular,debug.section__DWARF,__debug_ranges,regular,debug.section__DWARF,__debug_macinfo,regular,debug.section__DWARF,__debug_inlined,regular,debugLset21 = Ldebug_inlined_end1-Ldebug_inlined_begin1.longLset21Ldebug_inlined_begin1:.short2.byte8Ldebug_inlined_end1:.subsections_via_symbols

可以看到里面有很多关于debug的信息,使用MachOView工具也可以看到对应的可执行文件中的调试信息。


Q: 如何调试core文件?

A: 可以使用gdb  可执行文件  core文件 的方式来调试。如下,写个可以导致崩溃的代码invalid_ptr.c:

#include <stdio.h>int main(){    int *p = (int *)0;    *p = 1;    return 0;}
使用-g参数编译成可执行文件invalid_ptr.先查看下系统是否支持生成core文件,

如果是0,那说明不能生成core文件。做如下修改:

接着运行invalid_ptr文件:

注意上面的这个过程可能很慢,因为mac下生成的core文件异常的大,就这个代码,在笔者的机器上core文件有340MB,有点费解。

然后使用gdb调试此core文件(命令行中的/cores/core.13890是刚刚生成的core文件,不同平台可能不同,需要根据时间自行判断):

可以看到,它正确地定位到了错误代码的位置。


Q: 如何能够得到一个变量的类型?

A: 使用whatis命令即可。如下代码保存为mem.c:

#include <stdio.h>int main(){    int arr[] = {1, 2, 3, 4};    arr[0] = 100;    return 0;}
使用gdb调试:


Q: 在gdb环境,需要调用外部shell命令,如何不退出gdb来执行?

A: 使用shell命令即可。

上面是在gdb环境输出hello.c文件的内容。


Q: 有的时候,调试外部代码,为了给外部代码返回正确的数值,强制让一个函数返回某个特定的值,如何做?

A: 使用return命令。如下代码,保存为add.c, 并进入gdb调试状态:

#include <stdio.h>int add(int a, int b){    return a + b;}int main(){    int i = 2;    int sum;    printf("%d\n", i);    sum = add(i, 3);    printf("sum is %d\n", sum);    return 0;}
如下调试:

可以看到,add函数,参数为2和3,但是可以强制改变它的返回值。


Q: 有的时候,需要修改某个变量的值来调试查看可能的结果,怎么做?

A: 可以使用set  var命令。使用上面的代码,进入调试状态:

可以看到使用set  var  i=100将i的数值改变了。


Q: 如果需要查看当前执行的函数的内部基本信息,怎么办?

A: 可以使用info  frame命令(缩写为i  f).依然使用上面的add.c代码,进入调试状态:

可以看到,里面包含了语言、参数、局部变量和一些寄存器信息等。


Q: 如果需要输出某个地址的数据,用什么命令?

A: 可以使用print  *地址命令。依然使用add.c代码,进入调试状态:

对于内存地址的查看,也可以使用x命令查看。


Q: 有的时候,想直接跳到某一行执行,怎么做?

A: 使用jump命令。如下代码,为loop.c:

#include <stdio.h>int main(){    int i = 2;    while(i < 1000)    {        ++i;    }    printf("end...\n");    return 0;}
假设在while循环中有断点,想要直接跳到后面的printf函数:


Q: 如果在调试状态,需要主动调用某个函数,求其返回值,怎么做?

A: 可以使用call命令。使用add.c代码:

#include <stdio.h>int add(int a, int b){    return a + b;}int main(){    int i = 2;    int sum;    printf("%d\n", i);    sum = add(i, 3);    printf("sum is %d\n", sum);    return 0;}
进入调试状态:


Q: 如果是多线程,如何给不同线程执行的代码打断点?

A: 可以使用info  threads获取所有线程信息,然后使用b  行号  thread  线程号  来打断点。


xichen

2012-5-22 11:11:34




原创粉丝点击