栈溢出

递归调用,栈深度。

错误原因: java.lang.StackOverflowError  栈内存溢出

栈溢出 产生于递归调用,循环遍历是不会的,但是循环方法里面产生递归调用, 也会发生栈溢出。

解决办法:设置线程最大调用深度  

-Xss5m 设置最大调用深度

小伙伴,玩个好玩的,最大默认深度:

package jvmTest;

//打印堆的基本内存信息
public class Test02 {
     private static int count;
     public static void count(){
        try {
             count++;
             count(); 
        } catch (Throwable e) {
            System.out.println("最大深度:"+count);
            e.printStackTrace();
        }
     }
     public static void main(String[] args) {
         count();
    }

  }    

结果:

配置下 可以加大深度调用

来个猛烈的~~

运行结果:

 6666 好玩不

### 栈溢出漏洞的原理 栈溢出漏洞是由于程序在运行过程中,向栈中写入的数据超出了栈缓冲区的容量限制所导致的一种安全问题。栈是一种后进先出(LIFO)的数据结构,用于存储局部变量、函数调用的参数和返回地址等信息。当程序错误地修改了栈指针,或者在局部缓冲区中存储了过多的数据时,就会发生栈溢出[^1]。 攻击者可以通过覆盖栈上的返回地址,使程序跳转到他们指定的代码段执行,从而获取对系统的控制权。这种攻击通常利用恶意构造的输入数据,例如通过`gets()`函数读取用户输入时,如果未对输入长度进行限制,就可能导致缓冲区溢出[^2]。 以下是一个简单的栈溢出示例代码: ```c #include <stdio.h> #include <string.h> void input(char *s) { gets(s); // 不安全的函数,容易引发栈溢出 } int main() { char s[10]; input(s); return 0; } ``` 在此代码中,`char s[10]`定义了一个大小为10字节的栈缓冲区。如果输入的字符串长度超过10字节,则会导致栈溢出,覆盖相邻的栈内存区域,包括返回地址[^3]。 --- ### 栈溢出漏洞的修复方法 为了避免栈溢出漏洞,可以采取以下措施: 1. **代码审查**:通过代码审查发现可能导致栈溢出的代码段,并进行修复。例如,避免在栈上分配过大的数组或结构体,确保递归调用有正确的终止条件等[^4]。 2. **使用栈保护技术**:现代编译器和操作系统提供了栈保护技术,如Canary机制。通过在栈上保存一个随机值(Canary值),并在函数返回前检查该值是否被修改,可以检测并防止栈溢出攻击[^4]。 3. **限制递归深度**:对于递归函数,可以设置递归深度的限制,以避免无限递归导致的栈溢出。 4. **优化数据结构**:使用更合适的数据结构来存储数据,可以减少栈空间的使用。例如,可以使用链表代替数组来存储大量数据。 5. **增加栈空间**:在某些情况下,可以通过增加栈空间的大小来避免栈溢出。然而,这并不是一个长期的解决方案,因为过大的栈空间可能会导致其他问题,如内存浪费和性能下降。 6. **使用动态内存分配**:对于需要大量内存的数据结构或算法,可以考虑使用动态内存分配(如堆空间)来存储数据,而不是在栈上分配大量内存。 7. **遵循安全编程实践**:遵循安全编程实践,如输入验证、错误处理和异常处理,可以减少栈溢出的风险。例如,使用`fgets()`替代`gets()`函数,以限制输入长度。 --- ### 示例修复代码 以下是上述栈溢出示例代码的修复版本: ```c #include <stdio.h> #include <string.h> #define MAX_LEN 10 void input(char *s) { fgets(s, MAX_LEN, stdin); // 使用fgets替代gets,限制输入长度 s[strcspn(s, "\n")] = '\0'; // 去除可能存在的换行符 } int main() { char s[MAX_LEN]; input(s); printf("Input: %s\n", s); return 0; } ``` 在修复后的代码中,使用了`fgets()`函数替代`gets()`,并设置了输入的最大长度,从而有效避免了栈溢出问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值