【问题标题】:Why would buffer overruns cause segmentation faults when accessing an integer?为什么在访问整数时缓冲区溢出会导致分段错误?
【发布时间】:2009-12-03 23:15:08
【问题描述】:

在从函数 A() 调用函数 B() 期间,B() 分配一个 100 字符的数组并对其进行多次填充,包括一次使用 101 字符的字符串和一次使用 110 字符的字符串。这是一个明显的错误。

后来,函数 A() 尝试访问完全不相关的 int 变量 i,结果出现分段错误。

我明白为什么会发生缓冲区溢出,但是为什么我在访问这个整数时会出现分段错误?为什么我不简单地获取垃圾数据?

【问题讨论】:

    标签: c++ c segmentation-fault buffer-overflow


    【解决方案1】:

    缓冲区溢出可能会破坏堆栈上先前保存的帧指针版本。 当函数返回时,这个损坏的版本被加载到帧指针寄存器中,导致你描述的行为。

    Wikipedia's page 包含一个图形和定义。

    【讨论】:

      【解决方案2】:

      A() 调用B() 时,B 的前导指令会保存 A 的帧指针——A 保存局部变量的堆栈位置,然后用 B 自己的帧指针替换它。它看起来像这样:

      当 B 超出其局部变量时,它会弄乱将重新加载到帧指针中的值。这是作为帧指针值的垃圾,因此 A 的所有局部变量都被丢弃。更糟糕的是,未来对局部变量的写入会扰乱属于​​其他人的内存。

      【讨论】:

        【解决方案3】:

        您描述的最可能的解释是 B 中的溢出破坏了 A 堆栈上保存的帧指针。因此,在 B 返回后,A 的帧指针中有垃圾,并在尝试访问局部变量时崩溃。

        【讨论】:

          【解决方案4】:

          如果你通过指针访问 i,那么问题是指针是垃圾。

          【讨论】:

            【解决方案5】:

            重要的是要记住,您为 nul 终止字符分配了足够的内存加上一个(精明的读者会指出这个 nul,这主要是有原因的 - 一个带有一个 'l' 的 nul 是 '\0' [谢谢用于指出错误的软件猴子!],带有两个 'l' 的 null 是指向空的指针)。

            这是一个如何发生段错误的示例

            int main(int argc, char **argv){ int *x = NULL; *x = 5; // 繁荣 }

            由于 x 是一个指针并设置为 null,我们尝试取消引用该指针并为其分配一个值。一种有保证的产生分段错误的方法。

            有一个老技巧可用,您实际上可以捕获 seg 错误并获取堆栈跟踪,这在 unix 环境中更常见,方法是设置信号处理程序来捕获 SIGSEGV,并在您的信号处理程序中调用类似这个:

            字符缓冲区[250]; buf[0] = '\0'; sprintf(buf, "gdb -a %d | where > mysegfault.txt", getpid()); 系统(缓冲区);

            这会将当前执行的 C 程序和 shell 附加到调试器并将其自身附加到它,它的 where 部分显示导致 seg 错误的违规行的堆栈跟踪,并将输出重定向到当前目录。

            注意:这是实现定义的,取决于安装,在 AIX 下,gnu 调试器存在,因此这将起作用,您的里程可能会有所不同。

            希望这会有所帮助, 最好的祝福, 汤姆。

            【讨论】:

            • 其实一个nul就是ASCII控制字符'\0'; “0”是 ASCII 48。
            • @Software Monkey:感谢您的提醒,是的,您是正确的!当我使用反引号时,反斜杠以某种方式被转义了......我编辑了这个来计算你的评论!谢谢! :(
            猜你喜欢
            • 2017-05-12
            • 2016-07-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-17
            • 2010-10-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多