精华内容
下载资源
问答
  • 20.11.23堆的概念C表述栈在程序中的应用栈溢出 堆的概念C表述 栈在程序中的应用 我的理解: 在程序运行过程中,当要调用某个子函数时: 将主函数的相关参数压入栈中、将call指令的下一条指令的地址作为返回地址压...

    栈在程序中的应用

    我的理解
    在程序运行过程中,当要调用某个子函数时:
    将子函数的相关参数压入栈中、将call指令的下一条指令的地址作为返回地址压入栈中、将当前ebp入栈、使ebp指向esp所指的位置(重新定位栈底)、将esp指向的地址+xxxH(在栈上分配xxx字节的空间)(可选)、将某些寄存器中的值入栈(可选)、将某些寄存器中的值出栈(可选)、使esp指向ebp所指向的位置(恢复esp同时回收局部变量的空间)、弹出之前压入的ebp地址到ebp(恢复ebp)(弹出ebp地址时会使esp+4H指向返回地址即栈顶)、如果有返回值那么将返回值传入eax、执行ret指令回到主函数继续执行指令,子函数调用参数并不是用“pop”指令而是引用(如:“mov eax,4(ebp)"),在恢复栈的同时会释放子函数所相对的栈空间。
    Alt
    Alt

    i386函数体的开头一般是这样的:

    push ebp;保存调用前的ebp值
    mov ebp,esp;ebp指向栈中保存调用前ebp值的位置
    sub esp,xxx;在栈上分配xxx字节的空间,这个是可选的
    push xxx;保存xxx寄存器的值,这个也是可选的

    在函数返回时,一般是这样的:

    pop xxx;恢复寄存器的值;如果开头有push xxx
    mov esp,ebp;恢复esp,同时回收局部变量的空间
    pop ebp;恢复调用前ebp的值
    mov eax,xxx;如果函数有返回值,那么返回值一般放在eax中
    ret;从栈中取回返回地址,并跳转到该位置

    栈溢出

    栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。
    因为在内存中写入数据是由低地址向高地址写入而栈是由高地址向低地址生长,所以当向栈中某个变量写入的字节数超过这个变量本身所申请的字节数时会覆盖该变量后面的数据,当覆盖的是main函数的ebp时会修改ebp使得栈不平衡、改变了栈底,当覆盖的是返回地址时会使得程序执行非原指令、可使覆盖返回地址的数据是攻击代码的地址来获取shell。

    Alt

    展开全文
  • 栈在递归中的应用

    2021-03-30 22:43:46
    函数调用背后的过程 递归:若在一个函数、过程或数据结构的定义中又应用了它自身,则这个函数、过程或数据结构...栈在递归中的应用 int Fib(int n) //斐波那契数列的实现 { if(n == 0) return 0; //边界条件 else i

    函数调用背后的过程

    递归:若在一个函数、过程或数据结构的定义中又应用了它自身,则这个函数、过程或数据结构称为是递归定义的,简称递归。

    在这里插入图片描述
    它通常把一个大型的复杂问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的代码就可以描述出解题过程所需要的多次重复计算,大大减少了程序的代码量,但在通常情况下,它的效率并不是很高。
    在这里插入图片描述

    栈在递归中的应用

    在这里插入图片描述

    int Fib(int n) //斐波那契数列的实现
    {
       if(n == 0)
           return 0; //边界条件
       else if(n == 1)
           return 1; //边界条件
       else
           return Fib(n-1) + Fib(n-2); //递归表达式
    

    必须注意递归模型不能是循环定义的,其必须满足下面的两个条件:
    1)递归表达式(递归体)
    2)边界条件(递归出口)
    递归的精髓在于能否将原始问题转换为属性相同但规模较小的问题。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在递归调用过程中,系统为每层的返回点、局部变量、传入实参等开辟了递归工作栈来进行数据存储,递归次数过多容易造成栈溢出等。而其效率不高的原因是递归调用过程中包含很多重复的计算。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Linux系统的应用程序中写一个函数print_stackframe(),用于获取当前位置的函数调用信息 方法 execinfo.h库下的函数backtrace可以得到当前线程的函数调用指针和调用深度,backtrace_symbols可以将调用指针...

    在Linux中打印函数调用栈
    要求

    在Linux系统的应用程序中写一个函数print_stackframe(),用于获取当前位置的函数调用栈信息
    方法

    execinfo.h库下的函数backtrace可以得到当前线程的函数调用栈指针和调用栈深度,backtrace_symbols可以将调用栈指针转化为字符串信息。详见Backtraces或在Linux命令行运行命令man backtrace.
    测试平台

        Linux内核版本:Linux version 4.15.0-45-generic (buildd@lcy01-amd64-027)
        gcc版本:gcc version 5.4.0 20160609
        Ubuntu版本:Ubuntu 16.04.5 LTS

    代码

     1 // Created Time:    2019-03-08 09:48:30                                               
     2 // Modified Time:   2019-03-08 10:45:25
     3  
     4 #include <stdio.h>
     5 #include <execinfo.h>
     6  
     7 #define MAX_DEPTH (20)
     8  
     9 void func0(void);
    10 void func1(void);
    11 void func2(void);
    12 void print_stackframe(void);
    13  
    14 void print_stackframe(void)
    15 {
    16     void * buffer[MAX_DEPTH];
    17     int depth = backtrace(buffer, MAX_DEPTH);
    18     char ** func_names = backtrace_symbols(buffer, depth);
    19     for (int i=0; i<depth; i++)
    20     {
    21         printf("Depth: %d, func name: %s\n", i, func_names[i]);
    22     }
    23 }
    24  
    25 void func0(void)
    26 {
    27     func1();
    28 }
    29  
    30 void func1(void)
    31 {
    32     func2();
    33 }
    34  
    35 void func2(void)
    36 {
    37     print_stackframe();
    38 }
    39  
    40 int main(int argc, char *argv[]) {
    41     // print_stackframe();
    42     func0();
    43     return 0;
    44 }

     

    编译运行

    gcc编译时加上-rdynamic参数,通知链接器支持函数名功能(不加-rdynamic参数则无函数名打印):

    gcc print_stackframe.c -o print_stackframe -rdynamic

        1

    运行可执行文件:

    ./print_stackframe

        1

    结果

    Depth: 0, func name: ./print_stackframe(print_stackframe+0x2e) [0x400964]
    Depth: 1, func name: ./print_stackframe(func2+0x9) [0x400a15]
    Depth: 2, func name: ./print_stackframe(func1+0x9) [0x400a09]
    Depth: 3, func name: ./print_stackframe(func0+0x9) [0x4009fd]
    Depth: 4, func name: ./print_stackframe(main+0x14) [0x400a2c]
    Depth: 5, func name: /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f7abe418830]
    Depth: 6, func name: ./print_stackframe(_start+0x29) [0x400869]
     
    原文链接:https://blog.csdn.net/da_kao_la/article/details/88343534

    展开全文
  • 程序的入口是 main 函数,刚开始运行 main 函数时候,会把 main函数相关一些必要信息压入栈,比如 main 函数里面局部变量 a、b、c。 为了保证程序运行顺序正确性 (从计算机思维),...

    =>  递归算法即递归函数调用自身的过程,递归的过程背后就是函数调用的过程!

     

    1. 函数调用的背后过程

     

    任何一段代码、任何一个程序调用之前,系统都会开辟一个函数调用栈。用这个栈来保存各个函数在调用过程当中所必须保存的一些信息。包括:调用返回地址、实参、局部变量

     

    程序的入口是 main 函数,刚开始运行 main 函数的时候,会把 main 函数相关的一些必要信息压入栈中,比如 main 函数里面的局部变量 a、b、c。

    为了保证程序运行顺序的正确性 (从计算机的思维),会在调用 funct 1 这个函数的时候,把func 1 执行结束之后应该执行的代码的存储地址(#1) 压入栈中。    除此之外,函数调用的两个参数 (a,b) 也会压入栈中。所以这也是为什么当调用函数的时候,可以将一个 视为“原件” ,一个视为“复印件”  (比如 func 1 中修改 a,b 的值,其实修改是另一内存中 a,b 的值, main 函数里面的 a,b 值并不受影响)       除了被调用函数的实参之外,该函数定义的局部变量 x 也会压入栈中。   

    func 2 函数调用过程类似分析。 当 func 2 函数执行完了之后,会根据栈顶地址信息( #2 ) 找到下一句将执行的代码, 然后将 func 2 函数相关的信息弹出栈!(即释放 func 2 占用的内存空间),当 func 1  函数执行完后,同样会根据栈顶地址信息( #12 ) 找到下一句将执行的代码, 然后将 func 1 函数相关的信息弹出栈!然后执行 main 函数剩下的代码!

     

    从我们的视角来看,程序是从 main 函数开始执行的,但其实程序在经过编译之后,编译器会在 main 函数之前还加一些其它的代码,那些代码执行完了之后,才会调用 main 函数,执行 main 函数相关的东西。(上面的栈图中 main 函数之前有一些 ..... )

    小结:只要涉及到函数调用背后就要栈的支持。

     

    IDE中通过 debug 方式可以进行观察函数调用栈中保存了哪些东西。

     

     

     

     

    2. 栈在递归问题中的使用

    很多问题都可以用递归的方式来解决,这类问题的特点是: 可以把原始问题转换为 属性相同、但规模较小的问题。

     

    这里的重点的并不是如何设计一个递归算法,而是这个递归算法它背后和栈有什么联系。

     

     

     

     

    缺点:太多层递归可能导致栈溢出!(比如这里计算 100000! )
               递归算法的空间复杂度 !!!

     

     

     

     

    展开全文
  • 它具有抽象层,因此调用应用程序不需要了解内部结构。 该项目最初Codeproject( )上发布。 但是很难codeproject上维护文章和源代码,因此我被迫“易于修改”平台上发布源代码。 因此,我选择了“ ...
  • 同时,它前端中的应用也非常广泛,很多小伙伴都会误以为 `` 前端中的应用很少,但殊不知的是,我们写的每一个程序,基本上都会用到 `` 这个数据结构。比如,函数调用堆栈、数据的深拷贝和浅拷贝……。 所以...
  • 假设表达式允许包含两种括号:圆括号和方括号,其嵌套顺序任意即()或[([][])]等均为正确格式,[(]或([())或(()]均为不正确格式。 void test() { int a[10][10]; int x = 10*(20*(1+1)-(3-2)); printf(...
  • 我们可以使用backtrace工具,更详细可以参见如下博客https://blog.csdn.net/ieearth/article/details/49763481 转载于:https://www.cnblogs.com/xingmuxin/p/11413598.html
  • 表达式求值是程序设计语言编译一个最基本问题,它实现是栈应用的一个典型范例。 波兰数学家灵感 中缀、后缀、前缀表达式 中缀表达式不仅依赖运算符优先级,而且还要处理括号。 后缀表达式运算符操作...
  • 在应用程序中输出函数调用

    千次阅读 2010-06-25 15:38:00
    但是在应用程序中我们该如何输出函数调用呢? Linux下我们可以是用下面函数。// 获取将backstrace信息,将地址存到buffer中。 // 参数size指定buffer最大值,返回值则是backstrace实际大小 int ...
  • 退出应用程序

    2017-06-17 19:03:11
    1.首先你要做退出应用程序,你就需知道如果为了更加便利,在栈中有多个Activity,就可把看成一个集合 2.于是我们需要建一个application类,来实现自己application 3.然后实现效果 二.下面是效果图以及 (2)...
  • 程序让我更好的理解了“”这种结构数据结构中的重要地位!
  • 栈的应用

    2021-04-15 16:07:26
    1、子程序调用:跳往子程序前,会将下个指令地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。 2、处理递归调用:和子程序调用类似,除了存储下一个指令地址外,也将参数、区域变量等...
  • 数据结构-栈在括号匹配中的应用

    千次阅读 2018-10-22 10:58:01
    程序也运用了栈的思想。若是左括号则入栈,若是右括号则看是否和当前栈顶元素是否匹配。若是则出栈,不是则当前表达式括号不匹配。 程序思想: 1.初始设置一个空栈,顺序读入括号。 2.若是右括号,则使置于栈顶...
  • 利用编写简单行编辑程序:接受用户从终端输入的程序或数据,输入过程,允许用户输入出差错,并发现有误时可以及时更正。例如:当用户发现刚刚键入一个字符是错时,可以补进一个退格符“#”,以表示前...
  • 其操作方式类似于数据结构中的栈。 2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)...
  • 搭建了一个基于DSP嵌入式系统以太网接入硬件平台,给出了软件设计思路及具体实现方法,对开源uIP协议进行裁剪和修改,完成了设备驱动程序的开发和嵌入式uIP协议栈的移植,最终实现了嵌入式系统接入以太网...
  • Description 利用编写简单行编辑程序:接受用户从终端输入的程序或数据,输入过程,允许用户输入出差错,并发现有误时可以及时更正。例如:当用户发现刚刚键入一个字符是错时,可以补进一个退格符“#...
  • 用户输入一行过程,允许 用户输入出差错,并发现有误时 可以及时更正。 其合理做法是:设立一个输入缓冲区,用以接受用户输入一行字符,然后逐行存入用户数据区,并假设“#”为退格符,“@”为退行符。 ...
  • pilot是一种熟悉(android.*decoupled)堆栈结构建模应用程序状态方法,并为基于视图ui呈现提供钩子。这有助于:
  • 本关任务:编写一个能根据逆波兰表示法,求表达式的程序。 相关知识 为了完成本关任务,你需要掌握: 什么是逆波兰表达式; 和表达式求值关系。 逆波兰表达式(Reverse Polish notation,RPN) 逆波兰表达式...
  • 栈的应用

    2021-04-14 16:48:45
    当一个函数被调用时,一个返回地址( 即被调函数一旦执行完,接下去要执行的程序指令地址)和被调函数局部变量和形参值都要存储递归工作栈中。当执行一次返回时,被调函数局部变量和形参值被恢复为调用...
  • 栈的操作及应用

    2017-11-16 21:49:40
    理解栈在程序设计中的应用。 2.实验环境 Visual C++ 6.0 3.实验报告内容 (1)给出栈的顺序存储结构定义。 (2)给出在顺序存储结构上实现栈的入栈操作的基本设计思想,并用C语言实现。 (3)给出在顺序存储结构上...
  • @TOCZ-Stack协议中LED定义及应用 Z-Stack协议中LED定义及应用 2020年3月27日 CamusLu Z-Stack协议里面有三个LED灯定义。...程序中用于点亮一个LED灯由函数HalLedSet(HAL_LED_2,HAL_LED_M
  • 一、框架概念和使用 1、概念 框架是不同项目都要使用代码封装,是软件半成品。 2、框架具体表现形式 ...MVC代码结构,将Servlet和Service层、Service和Mapper层进行解耦。 3、使用
  • 栈在计算机的实现有多种方式:◆ 硬堆栈:利用CPU中的某些寄存器组或类似的硬件或使用内存的特殊区域来实现。这类堆栈容量有限,但速度很快;◆ 软堆栈:这类堆栈主要在内存中实现。堆栈容量可以达到很大。在实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,028
精华内容 2,411
关键字:

栈在程序中的应用