Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从被调用函数到被调用函数获取局部变量_C_Linux_Unix - Fatal编程技术网

C 从被调用函数到被调用函数获取局部变量

C 从被调用函数到被调用函数获取局部变量,c,linux,unix,C,Linux,Unix,所以,我有一个任务需要帮助。 我得到了一个名为foo()的函数和一个名为recover()的函数的代码。我无法更改foo的代码,recover不能有任何参数,并且不返回任何内容 这样做的目的是让recover从foo中获取局部变量并将其打印出来 例如: long foo(long a, long b, long c, long d, long e){ long x, y, z; if(e < 0) { recover(); return a;

所以,我有一个任务需要帮助。 我得到了一个名为foo()的函数和一个名为recover()的函数的代码。我无法更改foo的代码,recover不能有任何参数,并且不返回任何内容

这样做的目的是让recover从foo中获取局部变量并将其打印出来

例如:

long foo(long a, long b, long c, long d, long e){
   long x, y, z;
   if(e < 0)
   {
      recover();
      return a;
   }
   //do various things with a, b, and c, and store in x, y, and z respectively
   return foo(x,y,z,d+1,e-1)+a+b+c+d+e;
}

void recover(void)
{
   //What goes here to get the values?
}
long foo(长a、长b、长c、长d、长e){
长x,y,z;
if(e<0)
{
恢复();
返回a;
}
//使用a、b和c执行各种操作,并分别存储在x、y和z中
返回foo(x,y,z,d+1,e-1)+a+b+c+d+e;
}
无效恢复(无效)
{
//这里是什么来获取值的?
}
recover()应该做的是从foo()的每次调用中获取a、b和c值并打印出来。我也知道这个问题不允许使用全局变量


感谢您对这个问题的帮助。

听起来像是一个堆栈攻击练习

尝试定义一个局部变量,获取地址,然后修改该地址以进入堆栈(根据您的机器进行加法或减法),直到您最终指向调用函数中的变量为止


这是非常依赖于系统的,所以你需要做一些游戏来解决它。我建议使用一组已知的参数调用
foo
,并专门查找这些值,以确保查找的位置正确。一旦你弄明白了这一点,你将拥有对
foo

的任何调用的值警告:以下代码高度依赖于编译器/体系结构且不符合要求。使用它的风险自负

局部变量存储在堆栈中,因此您可以通过自己声明一个局部变量并四处移动来获取父函数的局部变量

首先向变量中添加一些易于发现的值(稍后将删除它们)

可能您正在使用PC,因此您的堆栈将向下扩展,而您的目标将向上扩展。环顾四周,直到你找到他们:

void recover(void)
{
    long p;
    long *q = &p;
    for (int i=0; i < 20; ++i)
    {
        printf("%d -> %ld\n", i, q[i]);
    }
}
void恢复(void)
{
长p;
长*q=&p;
对于(int i=0;i<20;++i)
{
printf(“%d->%ld\n”,i,q[i]);
}
}

当然,您也可以使用调试器

你真幸运:你可以看看这堆东西。堆栈布局在不同平台上是不相同的,所以我们不能给你一个总是有效的标准答案。我的意思是,它甚至在Linux支持的所有体系结构上都不相同。完全取决于您的CPU和指令集,有时甚至取决于编译器的配置(一些使堆栈破坏攻击更加困难的扩展可以显著修改布局)。最简单的方法是让编译器转储它为代码生成的程序集并读取它——或者在运行时使用调试器进行检查。这些变量中的一些也可能最终出现在寄存器而不是堆栈中。@Rhymoid,这一点很好;该函数不是一个
extern
,因此编译器可以选择完全内联调用,而不必在堆栈上存储局部变量。虽然
foo
是递归的,而且我不知道现在的C编译器是否足够聪明,可以进行TCO…@CharlesDuffy在一些流行的ABI(SysV和Microsoft都是x86-64)中,前几个参数必须通过寄存器传递。即使
foo
没有内联,参数也可能永远不会离开寄存器文件。
void recover(void)
{
    long p;
    long *q = &p;
    for (int i=0; i < 20; ++i)
    {
        printf("%d -> %ld\n", i, q[i]);
    }
}