实验代码之runaway.c

本章实验是说明深度递归要占用大量内存空间,需谨慎使用。
实验代码如下:

/* Example of deep recursion */
#include <stdio.h>
#include <stdlib.h>

int recurse(int x) {
    int a[1<<15];  /* 4 * 2^15 =  64 KiB */
    printf("x = %d.  a at %p\n", x, a); 
    a[0] = (1<<14)-1;
    a[a[0]] = x-1;
    if (a[a[0]] == 0)
	return -1;
    return recurse(a[a[0]]) - 1;
}

int main(int argc, char *argv[]) {
    int x = 100;
    if (argc > 1)
	x = atoi(argv[1]);
    int v = recurse(x);
    printf("x = %d.  recurse(x) = %d\n", x, v);
    return 0;
}

以上代码部分是在每次递归过程中分配了2^15*4大小的空间给数组,占用如此大的空间再进行深度递归调用,我们就会发现机器的内存空间明显捉襟见肘了。所以递归函数要慎重使用。

接下来是无输入时取实验参数100时输出结果:

zhaoxiaoan@zhaoxiaoan:/mnt/hgfs/CS2$ ./runaway
x = 100.  a at 0x7ffca9f53660
x = 99.  a at 0x7ffca9f33630
x = 98.  a at 0x7ffca9f13600
x = 97.  a at 0x7ffca9ef35d0
x = 96.  a at 0x7ffca9ed35a0
x = 95.  a at 0x7ffca9eb3570
x = 94.  a at 0x7ffca9e93540
x = 93.  a at 0x7ffca9e73510
x = 92.  a at 0x7ffca9e534e0
x = 91.  a at 0x7ffca9e334b0
x = 90.  a at 0x7ffca9e13480
x = 89.  a at 0x7ffca9df3450
x = 88.  a at 0x7ffca9dd3420
x = 87.  a at 0x7ffca9db33f0
x = 86.  a at 0x7ffca9d933c0
x = 85.  a at 0x7ffca9d73390
x = 84.  a at 0x7ffca9d53360
x = 83.  a at 0x7ffca9d33330
x = 82.  a at 0x7ffca9d13300
x = 81.  a at 0x7ffca9cf32d0
x = 80.  a at 0x7ffca9cd32a0
x = 79.  a at 0x7ffca9cb3270
x = 78.  a at 0x7ffca9c93240
x = 77.  a at 0x7ffca9c73210
x = 76.  a at 0x7ffca9c531e0
x = 75.  a at 0x7ffca9c331b0
x = 74.  a at 0x7ffca9c13180
x = 73.  a at 0x7ffca9bf3150
x = 72.  a at 0x7ffca9bd3120
x = 71.  a at 0x7ffca9bb30f0
x = 70.  a at 0x7ffca9b930c0
x = 69.  a at 0x7ffca9b73090
x = 68.  a at 0x7ffca9b53060
x = 67.  a at 0x7ffca9b33030
x = 66.  a at 0x7ffca9b13000
x = 65.  a at 0x7ffca9af2fd0
x = 64.  a at 0x7ffca9ad2fa0
x = 63.  a at 0x7ffca9ab2f70
x = 62.  a at 0x7ffca9a92f40
x = 61.  a at 0x7ffca9a72f10
x = 60.  a at 0x7ffca9a52ee0
x = 59.  a at 0x7ffca9a32eb0
x = 58.  a at 0x7ffca9a12e80
x = 57.  a at 0x7ffca99f2e50
x = 56.  a at 0x7ffca99d2e20
x = 55.  a at 0x7ffca99b2df0
x = 54.  a at 0x7ffca9992dc0
x = 53.  a at 0x7ffca9972d90
x = 52.  a at 0x7ffca9952d60
x = 51.  a at 0x7ffca9932d30
x = 50.  a at 0x7ffca9912d00
x = 49.  a at 0x7ffca98f2cd0
x = 48.  a at 0x7ffca98d2ca0
x = 47.  a at 0x7ffca98b2c70
x = 46.  a at 0x7ffca9892c40
x = 45.  a at 0x7ffca9872c10
x = 44.  a at 0x7ffca9852be0
x = 43.  a at 0x7ffca9832bb0
x = 42.  a at 0x7ffca9812b80
x = 41.  a at 0x7ffca97f2b50
x = 40.  a at 0x7ffca97d2b20
x = 39.  a at 0x7ffca97b2af0
x = 38.  a at 0x7ffca9792ac0
段错误 (核心已转储)

如上所示,我们知道机器的运行内存中空间是有限的,如果使用递归很容易发生严重的错误!

以下是该代码的汇编显示:

/*
zhaoxiaoan@zhaoxiaoan:/mnt/hgfs/CS2$ objdump -d runaway

runaway:     文件格式 elf64-x86-64


Disassembly of section .init:

0000000000000580 <_init>:
 580:	48 83 ec 08          	sub    $0x8,%rsp
 584:	48 8b 05 5d 0a 20 00 	mov    0x200a5d(%rip),%rax        # 200fe8 <__gmon_start__>
 58b:	48 85 c0             	test   %rax,%rax
 58e:	74 02                	je     592 <_init+0x12>
 590:	ff d0                	callq  *%rax
 592:	48 83 c4 08          	add    $0x8,%rsp
 596:	c3                   	retq   

Disassembly of section .plt:

00000000000005a0 <.plt>:
 5a0:	ff 35 0a 0a 20 00    	pushq  0x200a0a(%rip)        # 200fb0 <_GLOBAL_OFFSET_TABLE_+0x8>
 5a6:	ff 25 0c 0a 20 00    	jmpq   *0x200a0c(%rip)        # 200fb8 <_GLOBAL_OFFSET_TABLE_+0x10>
 5ac:	0f 1f 40 00          	nopl   0x0(%rax)

00000000000005b0 <__stack_chk_fail@plt>:
 5b0:	ff 25 0a 0a 20 00    	jmpq   *0x200a0a(%rip)        # 200fc0 <__stack_chk_fail@GLIBC_2.4>
 5b6:	68 00 00 00 00       	pushq  $0x0
 5bb:	e9 e0 ff ff ff       	jmpq   5a0 <.plt>

00000000000005c0 <printf@plt>:
 5c0:	ff 25 02 0a 20 00    	jmpq   *0x200a02(%rip)        # 200fc8 <printf@GLIBC_2.2.5>
 5c6:	68 01 00 00 00       	pushq  $0x1
 5cb:	e9 d0 ff ff ff       	jmpq   5a0 <.plt>

00000000000005d0 <atoi@plt>:
 5d0:	ff 25 fa 09 20 00    	jmpq   *0x2009fa(%rip)        # 200fd0 <atoi@GLIBC_2.2.5>
 5d6:	68 02 00 00 00       	pushq  $0x2
 5db:	e9 c0 ff ff ff       	jmpq   5a0 <.plt>

Disassembly of section .plt.got:

00000000000005e0 <__cxa_finalize@plt>:
 5e0:	ff 25 12 0a 20 00    	jmpq   *0x200a12(%rip)        # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
 5e6:	66 90                	xchg   %ax,%ax

Disassembly of section .text:

00000000000005f0 <_start>:
 5f0:	31 ed                	xor    %ebp,%ebp
 5f2:	49 89 d1             	mov    %rdx,%r9
 5f5:	5e                   	pop    %rsi
 5f6:	48 89 e2             	mov    %rsp,%rdx
 5f9:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
 5fd:	50                   	push   %rax
 5fe:	54                   	push   %rsp
 5ff:	4c 8d 05 7a 02 00 00 	lea    0x27a(%rip),%r8        # 880 <__libc_csu_fini>
 606:	48 8d 0d 03 02 00 00 	lea    0x203(%rip),%rcx        # 810 <__libc_csu_init>
 60d:	48 8d 3d 91 01 00 00 	lea    0x191(%rip),%rdi        # 7a5 <main>
 614:	ff 15 c6 09 20 00    	callq  *0x2009c6(%rip)        # 200fe0 <__libc_start_main@GLIBC_2.2.5>
 61a:	f4                   	hlt    
 61b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

0000000000000620 <deregister_tm_clones>:
 620:	48 8d 3d e9 09 20 00 	lea    0x2009e9(%rip),%rdi        # 201010 <__TMC_END__>
 627:	55                   	push   %rbp
 628:	48 8d 05 e1 09 20 00 	lea    0x2009e1(%rip),%rax        # 201010 <__TMC_END__>
 62f:	48 39 f8             	cmp    %rdi,%rax
 632:	48 89 e5             	mov    %rsp,%rbp
 635:	74 19                	je     650 <deregister_tm_clones+0x30>
 637:	48 8b 05 9a 09 20 00 	mov    0x20099a(%rip),%rax        # 200fd8 <_ITM_deregisterTMCloneTable>
 63e:	48 85 c0             	test   %rax,%rax
 641:	74 0d                	je     650 <deregister_tm_clones+0x30>
 643:	5d                   	pop    %rbp
 644:	ff e0                	jmpq   *%rax
 646:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
 64d:	00 00 00 
 650:	5d                   	pop    %rbp
 651:	c3                   	retq   
 652:	0f 1f 40 00          	nopl   0x0(%rax)
 656:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
 65d:	00 00 00 

0000000000000660 <register_tm_clones>:
 660:	48 8d 3d a9 09 20 00 	lea    0x2009a9(%rip),%rdi        # 201010 <__TMC_END__>
 667:	48 8d 35 a2 09 20 00 	lea    0x2009a2(%rip),%rsi        # 201010 <__TMC_END__>
 66e:	55                   	push   %rbp
 66f:	48 29 fe             	sub    %rdi,%rsi
 672:	48 89 e5             	mov    %rsp,%rbp
 675:	48 c1 fe 03          	sar    $0x3,%rsi
 679:	48 89 f0             	mov    %rsi,%rax
 67c:	48 c1 e8 3f          	shr    $0x3f,%rax
 680:	48 01 c6             	add    %rax,%rsi
 683:	48 d1 fe             	sar    %rsi
 686:	74 18                	je     6a0 <register_tm_clones+0x40>
 688:	48 8b 05 61 09 20 00 	mov    0x200961(%rip),%rax        # 200ff0 <_ITM_registerTMCloneTable>
 68f:	48 85 c0             	test   %rax,%rax
 692:	74 0c                	je     6a0 <register_tm_clones+0x40>
 694:	5d                   	pop    %rbp
 695:	ff e0                	jmpq   *%rax
 697:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
 69e:	00 00 
 6a0:	5d                   	pop    %rbp
 6a1:	c3                   	retq   
 6a2:	0f 1f 40 00          	nopl   0x0(%rax)
 6a6:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
 6ad:	00 00 00 

00000000000006b0 <__do_global_dtors_aux>:
 6b0:	80 3d 59 09 20 00 00 	cmpb   $0x0,0x200959(%rip)        # 201010 <__TMC_END__>
 6b7:	75 2f                	jne    6e8 <__do_global_dtors_aux+0x38>
 6b9:	48 83 3d 37 09 20 00 	cmpq   $0x0,0x200937(%rip)        # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
 6c0:	00 
 6c1:	55                   	push   %rbp
 6c2:	48 89 e5             	mov    %rsp,%rbp
 6c5:	74 0c                	je     6d3 <__do_global_dtors_aux+0x23>
 6c7:	48 8b 3d 3a 09 20 00 	mov    0x20093a(%rip),%rdi        # 201008 <__dso_handle>
 6ce:	e8 0d ff ff ff       	callq  5e0 <__cxa_finalize@plt>
 6d3:	e8 48 ff ff ff       	callq  620 <deregister_tm_clones>
 6d8:	c6 05 31 09 20 00 01 	movb   $0x1,0x200931(%rip)        # 201010 <__TMC_END__>
 6df:	5d                   	pop    %rbp
 6e0:	c3                   	retq   
 6e1:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)
 6e8:	f3 c3                	repz retq 
 6ea:	66 0f 1f 44 00 00    	nopw   0x0(%rax,%rax,1)

00000000000006f0 <frame_dummy>:
 6f0:	55                   	push   %rbp
 6f1:	48 89 e5             	mov    %rsp,%rbp
 6f4:	5d                   	pop    %rbp
 6f5:	e9 66 ff ff ff       	jmpq   660 <register_tm_clones>

00000000000006fa <recurse>:
 6fa:	55                   	push   %rbp
 6fb:	48 89 e5             	mov    %rsp,%rbp
 6fe:	48 81 ec 20 00 02 00 	sub    $0x20020,%rsp
 705:	89 bd ec ff fd ff    	mov    %edi,-0x20014(%rbp)
 70b:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
 712:	00 00 
 714:	48 89 45 f8          	mov    %rax,-0x8(%rbp)
 718:	31 c0                	xor    %eax,%eax
 71a:	48 8d 95 f0 ff fd ff 	lea    -0x20010(%rbp),%rdx
 721:	8b 85 ec ff fd ff    	mov    -0x20014(%rbp),%eax
 727:	89 c6                	mov    %eax,%esi
 729:	48 8d 3d 64 01 00 00 	lea    0x164(%rip),%rdi        # 894 <_IO_stdin_used+0x4>
 730:	b8 00 00 00 00       	mov    $0x0,%eax
 735:	e8 86 fe ff ff       	callq  5c0 <printf@plt>
 73a:	c7 85 f0 ff fd ff ff 	movl   $0x3fff,-0x20010(%rbp)
 741:	3f 00 00 
 744:	8b 85 f0 ff fd ff    	mov    -0x20010(%rbp),%eax
 74a:	8b 95 ec ff fd ff    	mov    -0x20014(%rbp),%edx
 750:	83 ea 01             	sub    $0x1,%edx
 753:	48 98                	cltq   
 755:	89 94 85 f0 ff fd ff 	mov    %edx,-0x20010(%rbp,%rax,4)
 75c:	8b 85 f0 ff fd ff    	mov    -0x20010(%rbp),%eax
 762:	48 98                	cltq   
 764:	8b 84 85 f0 ff fd ff 	mov    -0x20010(%rbp,%rax,4),%eax
 76b:	85 c0                	test   %eax,%eax
 76d:	75 07                	jne    776 <recurse+0x7c>
 76f:	b8 ff ff ff ff       	mov    $0xffffffff,%eax
 774:	eb 19                	jmp    78f <recurse+0x95>
 776:	8b 85 f0 ff fd ff    	mov    -0x20010(%rbp),%eax
 77c:	48 98                	cltq   
 77e:	8b 84 85 f0 ff fd ff 	mov    -0x20010(%rbp,%rax,4),%eax
 785:	89 c7                	mov    %eax,%edi
 787:	e8 6e ff ff ff       	callq  6fa <recurse>
 78c:	83 e8 01             	sub    $0x1,%eax
 78f:	48 8b 4d f8          	mov    -0x8(%rbp),%rcx
 793:	64 48 33 0c 25 28 00 	xor    %fs:0x28,%rcx
 79a:	00 00 
 79c:	74 05                	je     7a3 <recurse+0xa9>
 79e:	e8 0d fe ff ff       	callq  5b0 <__stack_chk_fail@plt>
 7a3:	c9                   	leaveq 
 7a4:	c3                   	retq   

00000000000007a5 <main>:
 7a5:	55                   	push   %rbp
 7a6:	48 89 e5             	mov    %rsp,%rbp
 7a9:	48 83 ec 20          	sub    $0x20,%rsp
 7ad:	89 7d ec             	mov    %edi,-0x14(%rbp)
 7b0:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
 7b4:	c7 45 f8 64 00 00 00 	movl   $0x64,-0x8(%rbp)
 7bb:	83 7d ec 01          	cmpl   $0x1,-0x14(%rbp)
 7bf:	7e 16                	jle    7d7 <main+0x32>
 7c1:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
 7c5:	48 83 c0 08          	add    $0x8,%rax
 7c9:	48 8b 00             	mov    (%rax),%rax
 7cc:	48 89 c7             	mov    %rax,%rdi
 7cf:	e8 fc fd ff ff       	callq  5d0 <atoi@plt>
 7d4:	89 45 f8             	mov    %eax,-0x8(%rbp)
 7d7:	8b 45 f8             	mov    -0x8(%rbp),%eax
 7da:	89 c7                	mov    %eax,%edi
 7dc:	e8 19 ff ff ff       	callq  6fa <recurse>
 7e1:	89 45 fc             	mov    %eax,-0x4(%rbp)
 7e4:	8b 55 fc             	mov    -0x4(%rbp),%edx
 7e7:	8b 45 f8             	mov    -0x8(%rbp),%eax
 7ea:	89 c6                	mov    %eax,%esi
 7ec:	48 8d 3d b3 00 00 00 	lea    0xb3(%rip),%rdi        # 8a6 <_IO_stdin_used+0x16>
 7f3:	b8 00 00 00 00       	mov    $0x0,%eax
 7f8:	e8 c3 fd ff ff       	callq  5c0 <printf@plt>
 7fd:	b8 00 00 00 00       	mov    $0x0,%eax
 802:	c9                   	leaveq 
 803:	c3                   	retq   
 804:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
 80b:	00 00 00 
 80e:	66 90                	xchg   %ax,%ax

0000000000000810 <__libc_csu_init>:
 810:	41 57                	push   %r15
 812:	41 56                	push   %r14
 814:	49 89 d7             	mov    %rdx,%r15
 817:	41 55                	push   %r13
 819:	41 54                	push   %r12
 81b:	4c 8d 25 86 05 20 00 	lea    0x200586(%rip),%r12        # 200da8 <__frame_dummy_init_array_entry>
 822:	55                   	push   %rbp
 823:	48 8d 2d 86 05 20 00 	lea    0x200586(%rip),%rbp        # 200db0 <__init_array_end>
 82a:	53                   	push   %rbx
 82b:	41 89 fd             	mov    %edi,%r13d
 82e:	49 89 f6             	mov    %rsi,%r14
 831:	4c 29 e5             	sub    %r12,%rbp
 834:	48 83 ec 08          	sub    $0x8,%rsp
 838:	48 c1 fd 03          	sar    $0x3,%rbp
 83c:	e8 3f fd ff ff       	callq  580 <_init>
 841:	48 85 ed             	test   %rbp,%rbp
 844:	74 20                	je     866 <__libc_csu_init+0x56>
 846:	31 db                	xor    %ebx,%ebx
 848:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
 84f:	00 
 850:	4c 89 fa             	mov    %r15,%rdx
 853:	4c 89 f6             	mov    %r14,%rsi
 856:	44 89 ef             	mov    %r13d,%edi
 859:	41 ff 14 dc          	callq  *(%r12,%rbx,8)
 85d:	48 83 c3 01          	add    $0x1,%rbx
 861:	48 39 dd             	cmp    %rbx,%rbp
 864:	75 ea                	jne    850 <__libc_csu_init+0x40>
 866:	48 83 c4 08          	add    $0x8,%rsp
 86a:	5b                   	pop    %rbx
 86b:	5d                   	pop    %rbp
 86c:	41 5c                	pop    %r12
 86e:	41 5d                	pop    %r13
 870:	41 5e                	pop    %r14
 872:	41 5f                	pop    %r15
 874:	c3                   	retq   
 875:	90                   	nop
 876:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
 87d:	00 00 00 

0000000000000880 <__libc_csu_fini>:
 880:	f3 c3                	repz retq 

Disassembly of section .fini:

0000000000000884 <_fini>:
 884:	48 83 ec 08          	sub    $0x8,%rsp
 888:	48 83 c4 08          	add    $0x8,%rsp
 88c:	c3                   	retq  
 */

我们可以看到,递归不仅仅使存储空间迅速减少,还会使代码在编译时变得更加复杂。所以一定要慎用递归!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值