zoukankan      html  css  js  c++  java
  • 算法竞赛入门经典_4.3_递归

    看代码

    #include <stdio.h>
    
    int f(int n){
        return n == 0?1:f(n-1)*n;
    }
    int main()
    {
        printf("%d
    ", f(5));
        return 0;
    }

    上面f函数使用了递归,递归由两部分组成,一是递归头,二是递归体。

    我们使用gcc调试工具

    H:编程书籍学习算法竞赛入门经典2代码算法入门经典第四章>b f
    'b' 不是内部或外部命令,也不是可运行的程序
    或批处理文件。
    
    H:编程书籍学习算法竞赛入门经典2代码算法入门经典第四章>gdb a.exe
    GNU gdb (GDB) 7.4
    Copyright (C) 2012 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i686-pc-mingw32".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from H:编程书籍学习算法竞赛入门经典2代码算法入门经典第四章a.
    exe...done.
    (gdb) l
    1       #include <stdio.h>
    2
    3       int f(int n){
    4               return n == 0?1:f(n-1)*n;
    5       }
    6       int main()
    7       {
    8               printf("%d
    ", f(5));
    9               return 0;
    10      }(gdb) l
    Line number 11 out of range; 4.3.1_递归阶乘.c has 10 lines.
    (gdb) b f
    Breakpoint 1 at 0x4013bd: file 4.3.1_.c, line 4.
    (gdb) s
    The program is not being run.
    (gdb) r
    Starting program: H:\2\a.exe
    [New Thread 3640.0x2420]
    
    Breakpoint 1, f (n=5) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) s
    
    Breakpoint 1, f (n=4) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) s
    
    Breakpoint 1, f (n=3) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) s
    
    Breakpoint 1, f (n=2) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) s
    
    Breakpoint 1, f (n=1) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) s
    
    Breakpoint 1, f (n=0) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) s
    5       }

    可以直接使用b f给函数设置断点,断点将设置在函数首部。使用s 进行单步执行,r运行

    (gdb) bt
    #0  f (n=5) at 4.3.1_递归阶乘.c:4
    #1  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    
    Breakpoint 1, f (n=4) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) bt
    #0  f (n=4) at 4.3.1_递归阶乘.c:4
    #1  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #2  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    
    Breakpoint 1, f (n=3) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) bt
    #0  f (n=3) at 4.3.1_递归阶乘.c:4
    #1  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #3  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    
    Breakpoint 1, f (n=2) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) bt
    #0  f (n=2) at 4.3.1_递归阶乘.c:4
    #1  0x004013cf in f (n=3) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #3  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #4  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    
    Breakpoint 1, f (n=1) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) bt
    #0  f (n=1) at 4.3.1_递归阶乘.c:4
    #1  0x004013cf in f (n=2) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=3) at 4.3.1_递归阶乘.c:4
    #3  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #4  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #5  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    
    Breakpoint 1, f (n=0) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;
    (gdb) bt
    #0  f (n=0) at 4.3.1_递归阶乘.c:4
    #1  0x004013cf in f (n=1) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=2) at 4.3.1_递归阶乘.c:4
    #3  0x004013cf in f (n=3) at 4.3.1_递归阶乘.c:4
    #4  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #5  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #6  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    5       }
    (gdb) bt
    #0  f (n=0) at 4.3.1_递归阶乘.c:5
    #1  0x004013cf in f (n=1) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=2) at 4.3.1_递归阶乘.c:4
    #3  0x004013cf in f (n=3) at 4.3.1_递归阶乘.c:4
    #4  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #5  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #6  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    5       }
    (gdb) bt
    #0  f (n=1) at 4.3.1_递归阶乘.c:5
    #1  0x004013cf in f (n=2) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=3) at 4.3.1_递归阶乘.c:4
    #3  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #4  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #5  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    5       }
    (gdb) bt
    #0  f (n=2) at 4.3.1_递归阶乘.c:5
    #1  0x004013cf in f (n=3) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #3  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #4  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    5       }
    (gdb) bt
    #0  f (n=3) at 4.3.1_递归阶乘.c:5
    #1  0x004013cf in f (n=4) at 4.3.1_递归阶乘.c:4
    #2  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #3  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    5       }
    (gdb) bt
    #0  f (n=4) at 4.3.1_递归阶乘.c:5
    #1  0x004013cf in f (n=5) at 4.3.1_递归阶乘.c:4
    #2  0x004013f6 in main () at 4.3.1_递归阶乘.c:8
    (gdb) s
    5       }

    使用bt查看调用栈,很容易理解递归调用的关系了,

    注:由于使用了调用栈,c语言支持递归,调用自己和调用其他函数,并没有本质上的不同

    在这里,我们把主函数中的5改成1000000,gdb运行之后显示如下

    (gdb) r
    Starting program: H:\2\a.exe
    [New Thread 4372.0x1e78]
    
    Program received signal SIGSEGV, Segmentation fault.
    0x004013c7 in f (n=1899934856) at 4.3.1_递归阶乘.c:4
    4               return n == 0?1:f(n-1)*n;

    Segmentation fault段错误。什么原因呢?

    H:编程书籍学习算法竞赛入门经典2代码算法入门经典第四章>size a.exe
       text    data     bss     dec     hex filename
      23448    1324    2608   27380    6af4 a.exe

    我们首先使用q退出刚才的gbd,使用size命令得到可执行文件中的各个段的大小

    其中text为正文段,data为数据段,bss段,总大小是27380,。

    注:正文段用于存储指令,数据段用来存储已初始化的全局变量,

    bss段用于存储未赋值的全局变量和所需的空间,所以每次递归调用都需要

    调用栈里面的栈帧,而当越界了,就是栈溢出

  • 相关阅读:
    c++编程和c在思想上最大的差别
    java反射field和method的顺序问题
    使用wireshark分析tcp/ip报文之报文头
    wireshark不支持抓localhost/127.0.0.1的包解决方法
    wireshark捕获表达式之Berkeley Packet Filter (BPF) syntax
    java replaceAll之$替换
    阿里云至今不支持组播,确实比较坑爹
    java安全体系之JCA、JCE、JAAS、JSSE及其关系
    一个风控计算负载过高到mysql主从拆分暴露的各种设计复杂性问题以及解决方法总结
    作为从业人员,如果一定要学一门新的编程语言,那么它一定是c++
  • 原文地址:https://www.cnblogs.com/ncgds/p/7442235.html
Copyright © 2011-2022 走看看