adv*_*oge 5 c stack pointers longjmp setjmp
我正在尝试测试我的两个函数,它们模仿setjmp和longjmp用于作业 - 这是非常困难的,因为我们不允许使用内置函数或汇编asm()来实现longjmp和setjmp函数.(是的,那真的是作业.)
问题:我一直收到错误的返回值.所以,简而言之,当main()调用foo()和foo()调用bar(),而bar()调用longjump()时,bar()不应该返回foo(),而是setjmp()应该返回main的返回值为1,应打印"error"(参见下面的main()).
相反,我的输出结果如下:
start foo
start bar
segmentation fault
Run Code Online (Sandbox Code Playgroud)
分段错误,我尝试通过使用malloc初始化指针*p来修复,但似乎没有做任何事情.虽然,分段错误,是我没有得到正确的返回值的原因?
码:
#include <stdio.h>
#include <stdlib.h>
int setjmp(int v);
int longjmp(int v);
int foo(void);
int bar(void);
int *add;
int main(void) {
int r;
r = setjmp(r);
if(r == 0) {
foo();
return(0);
} else {
printf("error\n");
return(2);
}
}
int _main(void) {
return(0);
}
int setjmp(int v)
{
add = &v;
return(0);
}
int longjmp(int v)
{
int *p;
p = &v;
*(p - 1) = *add;
return(1);
}
int foo(void) {
printf("start foo\n");
bar();
return(0);
}
int bar(void) {
int d;
printf("start bar\n");
longjmp(d);
return(0);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
实现setjmp()并longjmp()需要访问堆栈指针。不幸的是,您正在处理的分配明确禁止您使用所有合理的方法来执行此操作(即,使用汇编或使用编译器内置函数来访问堆栈指针)。
更糟糕的是,他们修改了示例代码中setjmp()和的定义longjmp()。参数需要是解析为数组的类型(例如,typedef int jmp_buf[1]),而不是int……
无论如何。您需要某种方法来可靠地从 C 中的堆栈帧中找到旧的堆栈指针。可能最好的方法是在堆栈上定义一个数组,然后查看它的“后面”......
void get_sp(void) {
int x[1];
sp = x[-1]; // or -2 or -3, etc…
Run Code Online (Sandbox Code Playgroud)
确切的偏移量将取决于您使用的编译器,以及您的函数采用的参数以及函数具有的其他局部变量。您需要进行一些实验才能做到这一点。在模拟器中运行您的应用程序,和/或查看生成的程序集,以确保您选择了正确的值。
同样的技巧可能会在从longjmp(). 但是,某些编译器优化可能会使这变得困难,尤其是在具有链接寄存器的体系结构上——例如 MIPS。确保禁用编译器优化。如果所有其他方法都失败了,您可能需要调用一个虚拟函数longjmp()来强制编译器将链接寄存器保存在堆栈中,而不是将它留在寄存器中(它不能被覆盖)。
| 归档时间: |
|
| 查看次数: |
1415 次 |
| 最近记录: |