为什么在访问整数时缓冲区溢出会导致分段错误?

发布于 2024-08-13 08:23:15 字数 207 浏览 10 评论 0原文

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

随后,函数 A() 尝试访问完全不相关的 int 变量 i,并发生分段错误。

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

During a call to function B() from function A(), B() allocates a 100-char array and fills it several times, including once with a 101-character string and once with a 110 character string. This is an obvious mistake.

Later, function A() tries to access completely unrelated int variable i, and a segmentation fault occurs.

I understand why the buffer overrun occurs, but why do I get a segmentation fault when I access this integer? Why is it that I don't simply get garbage data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

烟酉 2024-08-20 08:23:15

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

维基百科页面包含图形和定义。

A buffer overrun may clobber a previously saved version of the frame pointer on the stack.
When the function returns, this corrupt version is loaded into the frame pointer register, causing the behavior you describe.

Wikipedia's page contains a figure and definitions.

橙味迷妹 2024-08-20 08:23:15

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

Stack Frame

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

When A() calls B(), B's preamble instructions save A's frame pointer—the location on the stack where A keeps local variables, before replacing it with B's own frame pointer. It looks like this:

Stack Frame

When B overruns its local variables, it messes up the value which will be reloaded into the frame pointer. This is garbage as a frame pointer value, so all of A's local variables are trashed. Worse, future writes to local variables are messing with memory belonging to someone else.

落在眉间の轻吻 2024-08-20 08:23:15

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

The most likely explanation from you description is that the overrun in B corrupts the saved frame pointer on the stack for A. So after B returns, A has garbage in its frame pointer and crashes when it tries to access a local variable.

痞味浪人 2024-08-20 08:23:15

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

If you're accessing i through a pointer, then the problem is the pointer is garbage.

寻找我们的幸福 2024-08-20 08:23:15

重要的是要记住,为 nul 终止字符分配足够的内存加一(精明的读者会指出这个 nul,这主要是有原因的 - 带有一个 'l' 的 nul 是 '\0'< /code> [感谢 Software Monkey 指出错误!],带有两个“l”的 null 是指向任何内容的指针)。

下面是一个如何发生段错误的示例。

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

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

有一个老技巧,你可以通过设置一个信号处理程序来捕获 SIGSEGV,并在你的信号处理程序中调用这样的进程,实际上捕获 seg 错误并获取堆栈跟踪,这在 unix 环境中更常见

char buf[250];
buf[0] = '\0';
sprintf(buf, "gdb -a %d | where > mysegfault.txt", getpid());
system(buf);

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

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

希望这有帮助,
此致,
汤姆.

It is important to remember that you allocate enough memory plus one for the nul terminating character (Astute readers will point out this nul, that is primarily there for a reason - a nul with one 'l' is '\0' [Thanks Software Monkey for pointing out an error!], a null with two 'l' is a pointer pointing to nothing).

Here's an example of how a seg fault can occur

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

Since x is a pointer and set to null, we attempt to dereference the pointer and assigning a value to it. A guaranteed way of generating a segmentation fault.

There is an old trick available in that you can actually trap the seg fault and get a stack trace, more common on unix environment, by setting up a signal handler to trap a SIGSEGV, and within your signal handler invoke a process like this:

char buf[250];
buf[0] = '\0';
sprintf(buf, "gdb -a %d | where > mysegfault.txt", getpid());
system(buf);

This attaches the currently executing C program and shells out to the debugger and attaches itself to it, the where part of it shows the stack trace of the offending line that caused the seg fault and redirects the output to a file in the current directory.

Note: this is implementation defined, depending on the installation, under AIX, the gnu debugger is present and hence this will work, your mileage may vary.

Hope this helps,
Best regards,
Tom.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文