为什么在函数堆栈上返回值不安全

2024-03-25

我在阅读 bruce eckel 时遇到了以下段落......他试图解释为什么函数在堆栈上返回值不安全

现在想象一下如果一个普通函数尝试在堆栈上返回值会发生什么
您不能触及返回地址上方堆栈的任何部分,因此该函数必须将值推入返回地址下方。但是当执行汇编语言返回时,堆栈指针必须指向返回地址(或者在它的正下方,具体取决于您的机器),因此在返回之前,函数必须将堆栈指针向上移动,从而清除所有本地变量.如果您尝试在返回地址下方的堆栈上返回值,此时你会变得容易受到攻击,因为可能会出现中断。ISR 会将堆栈指针向下保存以保存其返回地址及其局部变量并覆盖你的返回值

您想帮助我理解粗体斜体文本吗?


假设您的应用程序中的某处有以下调用堆栈:

  1. 主要例程
  2. Function1 的局部变量
  3. Function2 的局部变量

在这种情况下,main 调用 function1,而 function1 调用 function2。

现在假设function2调用function3,并且function3的返回值返回到堆栈上:

  1. 主要例程
  2. Function1 的局部变量
  3. Function2的局部变量
  4. Function3的局部变量,包括返回值

Function3 将返回值存入堆栈,然后返回。返回意味着,再次减少堆栈指针,所以堆栈变成这样:

  1. 主要例程
  2. Function1 的局部变量
  3. Function2 的局部变量

你看,function3 的栈帧已经不在这里了。

好吧,实际上我撒了一点谎。堆栈框架仍然存在:

  1. 主要例程
  2. Function1 的局部变量
  3. Function2 的局部变量
  4. Function3的局部变量,包括返回值

因此,访问堆栈来获取返回值似乎是安全的。

但是,如果在 function3 返回之后、但在 function2 从堆栈获取返回值之前发生中断,我们会得到以下结果:

  1. 主要例程
  2. Function1 的局部变量
  3. Function2的局部变量
  4. 中断函数的局部变量

而现在栈帧真的被覆盖了,我们迫切需要的返回值已经消失了。

这就是为什么在堆栈上返回返回值不安全的原因。

该问题与这段简单的 C 代码中显示的问题类似:

char *buf = (char *)malloc(100*sizeof(char *));
strcpy (buf, "Hello World");
free (buf);
printf ("Buffer is %s\n",buf);

大多数时候,用于 buf 的内存仍将包含“Hello World”内容,但如果有人能够在调用 free 之后、调用 printf 之前分配内存,则可能会出现严重错误。一个这样的例子是在多线程应用程序中(我们已经在内部遇到了这个问题),如下所示:

THREAD 1:                                  THREAD 2:
---------                                  ---------
char *buf = (char *)malloc(100);
strcpy (buf, "Hello World");
free (buf);
                                           char *mybuf = (char *)malloc(100);
                                           strcpy (mybuf, "This is my string");
printf ("Buffer is %s\n",buf);

线程 1 的 printf 现在可以打印“Hello World”,也可以打印“This is my string”。任何事情都可能发生。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在函数堆栈上返回值不安全 的相关文章

  • 删除字符串 C 的第一个字符

    我试图删除字符串的第一个字符并保留其余部分 我当前的代码无法编译 我对如何修复它感到困惑 My code char newStr char charBuffer int len strlen charBuffer int i 1 char
  • MVC Core IActionResult 含义

    什么是IActionResult 我尝试查看 MSDN 和其他网站 但需要通用 常见 易于理解的答案 MSDN IActionResult https learn microsoft com en us dotnet api microso
  • 中间件 API 的最佳实践是什么? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我们正在开发一个中间件 SDK 采用 C 和 Java 语言 供游戏开发人员 动画软件开发人员 阿凡达开
  • 我们如何将数据从一个打开的表单传递到另一个打开的表单?

    winform中如何将数据从一个窗体传递到另一个打开的窗体 在 Windows 应用程序中 一个窗体打开另一个窗体 当我在父表单中输入一些数据时 这些数据将立即反映在另一个子表单中 这将如何发生 取决于你想要多花哨 最简单的方法就是直接调用
  • 如何“杀死”Pthread?

    我正在学习 Pthreads 并且想知道杀死这样一个对象的最佳方法是什么 在寻找类似的问题后 我无法找到 明确 的答案 但请随时向我指出任何相关问题 我正在使用一个小型客户端服务器应用程序 其中服务器主线程正在侦听套接字上的客户端连接 每次
  • 使用 Selenium for C# 登录 Facebook

    我一直在使用 Selenium C 框架并尝试进行 facebook 登录 但没有任何运气 这是我到目前为止得到的 基于这篇文章 使用 Selenium 测试 Facebook Connect 应用程序 https stackoverflo
  • 控制器中的异常处理 (ASP.NET MVC)

    当您自己的代码抛出异常并从控制器中的操作调用时 应该如何处理 我看到很多最佳实践的例子 其中根本没有 try catch 语句 例如 从存储库访问数据 public ViewResult Index IList
  • 替换 JSON 中的转义字符

    我想用空格替换 JSON 字符串中的 字符 我怎样才能做到这一点 我发现从 JSON 字符串中删除所有转义字符的最简单 最好的方法是将字符串传递到正则表达式 Unescape 方法 此方法返回一个没有转义字符的新字符串 甚至删除了 n t
  • Create CFrameWnd 给出了第一次机会异常——为什么?

    我正在尝试使用基于 CFrameWnd 的代码编写一个简单的 MFC 应用程序 该应用程序在可滚动窗口中绘制 下面的代码改编自 Prosise Programming Windows with MFC 第 2 版 第 89ff 页 当我在调
  • 在不使用 Thread.Sleep c# 的情况下延迟发送电子邮件

    我有一个 for 循环 它循环并每个循环发送一封电子邮件 现在我正在使用 thread sleep 但我希望用户仍然能够与程序交互 只需取消该循环即可 是否可以在不使用 thread sleep 的情况下做到这一点 您是否在 UI 线程上运
  • 简单的文档管理系统和API [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Qt mouseReleaseEvent() 未触发?

    我有一个显示图片的库 我们称之为 PictureGLWidget 其中 class PictureGLWidget public QGLWidget 所以 PictureGLWidget 扩展了 QGLWidget 在PictureGlWi
  • 如何解释“错误C2018:未知字符'0x40'?[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 在编译一些代码时 我收到以下信息 错误 C2018 未知字符 0x40 我想知道如何解决这样的问题 这是我要开始的地方
  • C 中什么函数可以替换字符串中的子字符串?

    给定一个 char 字符串 我想查找所有出现的子字符串并将其替换为备用字符串 我没有看到任何简单的函数可以实现这一点
  • 如何分析 VSCode 中函数的性能

    我用 C Golang 编写了一个程序 如何找到占用最高 CPU 周期的函数 目的是提高正在执行的程序的性能 2021 年 10 月 金香儿哈娜 https github com hyangah宣布 tweet https twitter
  • 如何使用简历实现一个“一网打尽”的异常处理程序?

    我想知道我怎样才能写一个抓住他们全部应用程序级别的异常处理程序将为用户提供恢复应用程序流程的选项 如果您正在运行 Windows 窗体应用程序 将处理程序添加到Application ThreadException event
  • 实体框架代理创建

    我们可以通过使用来停止在上下文构造函数中创建代理 this Configuration ProxyCreationEnabled false 在 EF 4 1 中创建代理有哪些优点和缺点 代理对于两个功能是必需的 延迟加载 导航属性在第一次
  • C/C++ 通过 Android NDK 在 JNI 中看不到 Java 方法

    我正在尝试从使用 NDK 构建的 C 类文件调用 Java 方法 它不断抛出常见的 未找到非静态方法 错误并导致整个 Android 应用程序崩溃 下面的代码片段 有些东西可能不需要 但我按原样保留它们 因为焦点 问题在于refreshJN
  • 编译器可以报告未知属性的错误吗?即使有范围?

    在N3291 7 6 1 3 5 属性语法和语义 decl attr grammar 关于如何属性是用我读过的源代码写的 使用一个属性范围令牌是有条件支持的 实现定义的行为 and For an 属性标记本国际标准中未指定 该行为是实现定义
  • 具有多种类型的 C# 泛型类型推断

    我有以下通用方法 用于将一种类型的输入对象序列化为超类型 如下所示 public string SerialiseAs

随机推荐

  • Selenium 在 Firefox 中使用过多 RAM

    我在 Firefox 中使用 selenium 来自动执行 Instagram 上的一些任务 它基本上在用户配置文件和通知页面之间来回切换 并根据找到的内容执行任务 它有一个无限循环来确保任务继续进行 我每隔几步就有 sleep 函数 但内
  • 即使用户也可以访问需要限制的APEX页面

    我创建了一个 4 页的应用程序 Home 管理页面 计算体重指数 About 然后我进入 gt shared components gt Select Authorization schema gt Create 我已将其命名为only a
  • Visual Studio 2012 的数据库资源管理器中缺少图表文件夹

    我正在设计一个网站 突然数据库图表文件夹从数据库资源管理器中消失了 我不知道发生了什么以及现在该怎么做 因为我迫切需要它来继续我的工作 手动将表添加到数据库对我来说不是一个选择 我找了一整天的解决方案 甚至重新安装了Visual Studi
  • React-ReduxReducers 中 Spread 语法的用途

    我试图理解扩展运算符的目的 根据我从文档中了解到的 扩展语法会复制现有对象 并在传入新对象时被覆盖 在下面的代码中 export default function reducer state user fetching false fetc
  • 使用 python 进行实时 mp3 ffmpeg 编码器时出错

    我有如下代码 我想录制声音并将每个 wav 帧转换为 mp3 格式 使用 ffmpeg 实时 import pyaudio sys import subprocess command ffmpeg y f wav i f mp3 proce
  • C/C++ va_list 未正确返回参数

    我在使用 va list 时遇到问题 下面的代码适用于 int main int f1 1 float m function n f1 float function int n va list mem list va start mem l
  • 有没有更短更简洁的方法来用Javascript隐藏和显示div?

    我正在创建一个仪表板 其中包含大约 20 个以 display none 开头的 div 当使用侧边栏中的 onClick 时 它将显示特定的 div 并隐藏所有其他 div 我使用了为每个 div 创建一个函数的经典解决方案 但是 它非常
  • 为什么我的输入值没有用 React 更新?

    我的组件中有以下代码 当我更新某些内容时 它会被调用 从而替换 UI 中的一堆内容 除了用户看到的输入值之外 所有内容都在更新 let input id discount geo segment value percentage disab
  • Javascript,从“”中删除类的最快方法

    我有一个 body 元素 在上面添加了一些类 我想删除no javascript在浏览器读取它之后 从中获取类 好吧 既然之间的额外空格并不重要 我会说 document body className document body class
  • 如何在 Jetpack Compose 中监听生命周期

    我正在使用 Jetpack Compose 创建一个应用程序 该应用程序在后台进行一些网络搜索 如果用户决定按后退按钮 我想取消搜索 所以我用了DisposableEffect Composable fun SecondScreen val
  • 操作栏上没有显示操作按钮? [复制]

    这个问题在这里已经有答案了 我正在关注以下教程开发者 android com http developer android com并尝试在操作栏上添加项目 尽管我添加了所有代码 但搜索操作显示为溢出元素而不是操作按钮元素 我尝试了带有软键盘
  • 从 MySQL 中选择随机行(有概率)

    我有一个 MySQL 表 其中有一行名为 cur odds 它是一个百分比数字 表示该行被选中的百分比概率 例如 当您运行 100 个查询时 如何进行查询以大约该频率实际选择行 我尝试了以下操作 但概率为 0 35 的行最终在大约 60 7
  • 在 cordova/on android 应用程序中,使用 https 的请求失败,但使用 http 的相同请求成功

    我有一个可以通过两个端口访问的后端服务器 一个使用 HTTP 另一个使用 HTTPS 它使用自签名证书 从我的 ionic cordova 混合应用程序中 当我使用 HTTP 请求运行时 它们都成功了 在第一次请求期间 我还添加了基本授权
  • jquery mobile在手机间隙中实现方向改变事件

    有人可以让我知道手机间隙中 jquery mobile 方向改变事件的正确代码吗 我在哪里以及如何实现这个orientationChange函数 window bind orientationchange orientationHandle
  • Python Selenium(等待帧、元素查找)

    我有这些包括 from selenium import webdriver from selenium common exceptions import NoSuchElementException from selenium webdri
  • Python-替换 CSV 文件中的行值

    我有这个数据集 XXXX XXXX 0 XXXX XXXX 0 XXXX XXXX 0 XXXX XXXX 0 XXXX XXXX 0 XXXX XXXX 0 XXXX XXXX 0 XXXX XXXX 0 基本上我想在每次运行程序后将第二
  • Rails 3.0.9 + Devise + Cucumber + Capybara 臭名昭著的“没有路线匹配 /users/sign_out”

    我正在使用 devise 1 4 2 和 Rails 3 0 9 cucumber rails 1 0 2 capybara 1 0 0 我有No route matches users sign out 当我点击注销时出现错误 我添加了
  • 为什么 git stash pop 说它无法从存储条目恢复未跟踪的文件?

    我有很多分阶段和未分阶段的更改 我想快速切换到另一个分支 然后再切换回来 所以我使用以下方法进行了更改 git stash push a 事后看来我可能可以使用 include untracked代替 all 然后 当我去弹出存储时 我收到
  • 子表单根据主表单的ID新建记录

    首先我想说 我是 Access 的初学者 我将感谢我能得到的每一点帮助 我创建了一个表单 显示一个带有三个子表单的表中的记录 记录和子表单具有一对多的关系 我现在正在为每个子表单创建按钮 以便在子表单中创建新记录 我已成功制作按钮并使用宏生
  • 为什么在函数堆栈上返回值不安全

    我在阅读 bruce eckel 时遇到了以下段落 他试图解释为什么函数在堆栈上返回值不安全 现在想象一下如果一个普通函数尝试在堆栈上返回值会发生什么您不能触及返回地址上方堆栈的任何部分 因此该函数必须将值推入返回地址下方 但是当执行汇编语