assembly 理论上,被调用者可以直接访问调用者中的堆栈变量而无需指针吗?

yuvru6vn  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(124)

C是按值传递的,这意味着每次调用函数时,所有参数都被复制到堆栈框架中。C也不支持内部函数,这些内部函数可以访问/修改词法封闭函数中的局部变量。虽然GNU C does as an extension。在C中 '通过引用传递' 的唯一方法是传递指针。虽然C++中有引用类型这些只是幕后的指针。
我在一个假设的低级类C语言中考虑了下面的场景。可能有一个函数声明在另一个函数内部,只对外部函数可见,并且只会被外部函数调用。如果我的理解是正确的,那么当调用内部函数时,堆栈指针会增加一个固定的数量,假设没有诸如可变大小对象之类的有趣事情。因此,在外部函数中声明的任何局部变量相对于堆栈指针的偏移量都是固定的,即使在内部函数中也是如此。理论上,它们可以像其他局部变量一样被访问,而不需要传递指针。当然,试图从外部函数外部访问和调用内部函数将试图访问外部函数中的生存期外的局部变量,并导致未定义的行为。
下面是一个例子:(同样,这个不是C,而是一个想象的类C语言

void (*address_to_inner)(void);
void outer(void) {
    int a = 10;
    void inner(void) {
        printf("%d\n", a);
    }
    inner(); // Prints 10
    address_to_inner = inner; // Not undefined behavior yet but not good
}
void another(void) {
    outer(); // Prints 10
    address_to_inner(); // Undefined behavior because inner() tries to access `a` after it was deallocated
}

我的想法是否适用于典型的体系结构,如x86或ARM?一些功能,如自动内存管理,在低级语言(如C)中不受支持,因为它们不受体系结构的原生支持,并且需要太多复杂的幕后工作,对于低级语言来说是可行的。但是我的场景 “可行” 对于低级语言来说是可行的吗?是否有任何架构或技术上的限制,我没有考虑到这将使实现这一不平凡的基础上如何堆栈/局部变量和函数调用工作?如果没有,为什么不?

91zkwejq

91zkwejq1#

因此,随着思维过程的发展,任何在外部函数中声明的局部变量都将相对于堆栈指针处于固定的偏移量,即使在内部函数中也是如此。
这是可行的,尽管你必须排除嵌套函数之间的函数调用,这也排除了它们之间的递归。让我们注意到Pascal嵌套函数可以相互调用,也可以递归调用。
Pascal的基于堆栈的静态链接机制适用于机器只有很少CPU寄存器的时候,因此大多数Pascal程序变量都Map到内存。
另一种可能性,适用于具有许多CPU寄存器(x64,RISC V,ARM)的机器,可能是在函数及其嵌套函数中以及在函数及其嵌套函数之间进行局部变量的寄存器分配。因此,正如局部变量可能存在于寄存器中一样,非局部变量也可能存在。这也将排除递归,但会产生性能差异。
最后,让我们提到内联,因为它通过避免使用局部变量的内存来实现我们对具有大量CPU寄存器的机器所期望的大量效率-一旦两个函数通过内联合并,它们共享相同的局部变量存储空间;内联甚至可以移除调用者获取的地址对,然后在被调用者中解引用,允许将这样的局部变量Map到寄存器,而不是在地址实际上必须被物化时所需要的内存。由于内联是通过编译器对函数的分析来完成的,因此它在允许一个函数调用另一个函数方面是灵活的,包括递归-尽管某些构造可能会禁用某些优化。

相关问题