从函数调用的函数调用直接返回main

时间:2017-05-17 04:28:54

标签: c

就像免责声明一样,这个问题与我所做的特定任务有关,我并不是要求任何人为我做作业。

所以基本上我应该实现一种从函数调用的函数调用直接返回main的方法。

部分规定是我们不能使用汇编语言指令,gcc的asm()或gcc内置的ins。在google上做了很多关于这方面的研究后,我无法找到任何要查看的例子,甚至是setjmp / longjmp的源代码(这个赋值的目的是复制这些功能)。我已经向更多年长的CS学生寻求建议,而且大多数人都无法帮助或告诉我他们非常确定这是不可能达到规定的。任何建议或指示(哈哈)将不胜感激。即使是正确方向的推动,也可能确认作业并不像我想的那么复杂,我将不胜感激!

到目前为止,我最好的尝试:

- 使用setjmp函数存储我们在main中停止的地址(所以类似于x = foo1();然后将x传递给setjmp(x))然后让foo2调用我的longjmp函数,在longjmp I& #39; ll函数为我的参数设置一个指针(* p),然后(* p-1)= main中x的地址。

这没有用,但我认为尝试更改调用堆栈中的返回地址是正确的想法,因为如果我理解正确,函数的参数直接位于堆栈中的返回地址之上

这是我写的代码:

int setjmp(int v);
int longjmp(int v);
int fun1(void); 
int fun2(void); 
int *add; //using global, not sure if best idea
int main(void)
{
    int x = setjmp(x);
    foo1();
    return 0;
}
int setjmp(int v)
{
  add = &v; //used a global variable
  return 0;
}
int longjmp(int v)
{
  int *p; //pointer
  p = &v; //save argument address
  *(p-1) = *add; //return address = address in main
  return 1;
}
int foo1(void)
{
    printf("hi1");
    foo2();
    printf("hi2");
    return 0;
}
int foo2(void)
{
    int a;      
    longjmp(a);
    return 0;
}//output SHOULD be "hi1"
 //output is currently "hi1" "hi2"

对于它没有评论的每一行的价值是作为骨架给出的,我无法改变它。

如果有什么事情发生,请提前打扰我,我是C的新手。谢谢。

2 个答案:

答案 0 :(得分:4)

  

“所以基本上我应该实现一种从函数调用的函数调用直接返回main的方法。”

这个要求是胡说八道。任何满足该要求的尝试都将导致垃圾代码。写这样的事情的训练是直接有害的做法。这是一个非常糟糕的任务,你的老师应该为教你不好的做法而感到羞耻,没有免责声明。在现实世界的节目中也没有理由做这样的事情。

您无法在纯C中实现setjmp / longjmp函数,您必须使用内联汇编程序。它们保存了程序计数器以及特定系统所需的其他类似功能。他们还干涉堆栈指针,这是他们危险的一个原因。

因此,在标准C中执行此操作的唯一方法是使用setjmp.h中的标准库函数setjmp / longjmp。这些被广泛认为非常糟糕和危险,因为它们导致不可读的意大利面条编程和许多形式的未定义行为。 C标准中未定义行为的一个示例:

  

在longjmp之后,尝试访问自动对象的值   存储持续时间,没有volatile限定类型,函数本地   包含对应的setjmp宏的调用,已被更改   在setjmp调用和longjmp调用之间

请勿使用这些功能。

话虽如此,这就是你编写可怕,危险程序的方式:

// BAD! NEVER WRITE SPAGHETTI CODE LIKE THIS!

#include <stdio.h>
#include <setjmp.h>
#include <stdbool.h>

static jmp_buf jmp_main;

void func2 (bool one_more_time)
{
  puts(__func__);
  if(one_more_time)
  {
    longjmp(jmp_main, !one_more_time);
  }
  printf("end of "); puts(__func__);
}

void func1 (bool one_more_time)
{
  puts(__func__);
  func2(one_more_time);
  printf("end of "); puts(__func__);
}

int main (void)
{
  bool one_more_time = (bool)!setjmp(jmp_main);
  puts(__func__);  
  func1(one_more_time);
  printf("end of "); puts(__func__);
}

输出:

main
func1
func2
main
func1
func2
end of func2
end of func1
end of main

答案 1 :(得分:0)

我认为问题并不复杂。你应该在返回值时调用另一个具有条件的函数,这样如果它是某个值(比如说0)那么返回,否则继续执行该函数。 因此,您只需将foo2();替换为:

即可
if (foo2() == 0) return 0;

现在在foo2()函数return 0;中,只要您希望返回foo1()的主函数调用,否则继续foo1()语句。你不需要在这里使用setjmp。

您可能还会发现此文章有用:Tread programming examples