python 堆栈溢出_内存 - 如何发生“堆栈溢出”,如何防止它?

在此上下文中,堆栈是在程序运行时放置数据的最后进先出缓冲区。 最后一次出来(LIFO)意味着你输入的最后一件事总是你要退回的第一件事 - 如果你在堆叠上推2个项目,'A'然后'B',那么你首先要弹出的东西 在堆栈中将是'B',接下来是'A'。

当您在代码中调用函数时,函数调用之后的下一条指令将存储在堆栈中,以及可能被函数调用覆盖的任何存储空间。 您调用的函数可能会为其自己的局部变量使用更多堆栈。 完成后,它释放它使用的局部变量堆栈空间,然后返回到上一个函数。

堆栈溢出

堆栈溢出是指您为堆栈耗尽的内存超出了程序应该使用的内存。 在嵌入式系统中,堆栈可能只有256个字节,如果每个函数占用32个字节,那么你只能有函数调用8深 - 函数1调用函数2调用函数3调用函数4 .... 函数8调用函数9,但函数9覆盖堆栈外的内存。 这可能会覆盖内存,代码等。

许多程序员通过调用函数A然后调用函数B来犯这个错误,然后调用函数C然后调用函数A.它可能在大多数情况下工作,但只是一次错误的输入将导致它永远进入该循环 直到计算机识别出堆栈被夸大了。

递归函数也是导致这种情况的原因,但是如果你正在递归编写(即,你的函数自己调用),那么你需要注意这一点并使用静态/全局变量来防止无限递归。

通常,您正在使用的操作系统和编程语言管理堆栈,而且它不在您的手中。 您应该查看您的调用图(从您的主要显示每个函数调用的树结构),以查看函数调用的深度,以及检测非预期的循环和递归。 如果他们互相称呼过多次,则需要人为地检查故意循环和递归以防错误。

除了良好的编程实践,静态和动态测试之外,您无法在这些高级系统上做太多事情。

嵌入式系统

在嵌入式领域,特别是在高可靠性代码(汽车,飞机,太空)中,您可以进行大量的代码审查和检查,但您还要执行以下操作:

禁止递归和循环 - 由策略和测试强制执行

保持代码和堆栈相隔很远(代码在flash中,堆栈在RAM中,而且twain不会满足)

将保护带放置在堆栈周围 - 空白的内存区域,您填充了一个幻数(通常是软件中断指令,但这里有很多选项),每秒数百或数千次看保护带以确保 他们没有被覆盖。

使用内存保护(即,堆栈上没有执行,堆栈外没有读取或写入)

中断不会调用辅助函数 - 它们设置标志,复制数据,并让应用程序负责处理它(否则你可能会在函数调用树中深入8,有一个中断,然后在内部运行另外几个函数) 中断,引起井喷)。 你有几个调用树 - 一个用于主进程,一个用于每个中断。 如果你的中断可以互相打断......好吧,有龙......

高级语言和系统

但是在操作系统上运行的高级语言:

减少局部变量存储(局部变量存储在堆栈中 - 尽管编译器非常聪明,如果调用树很浅,有时会将大型本地变量放在堆上)

避免或严格限制递归

不要将程序分解成越来越小的函数 - 即使不计算局部变量,每个函数调用在堆栈上消耗多达64个字节(32位处理器,节省一半CPU寄存器,标志等)

保持呼叫树浅(类似于上面的陈述)

Web服务器

它取决于您拥有的“沙盒”,无论您是否可以控制甚至看到堆栈。 很有可能你可以像对待任何其他高级语言和操作系统一样对待Web服务器 - 它很大程度上取决于你的手,但检查你正在使用的语言和服务器堆栈。 例如,可以在SQL服务器上清空堆栈。

-亚当

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值