C堆栈变量是否反向存储? [英] Are C stack variables stored in reverse?

查看:77
本文介绍了C堆栈变量是否反向存储?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解C如何在堆栈上分配内存.我一直认为栈上的变量可以像structs成员变量那样描述,它们占据了栈内连续的,连续的字节块.为了帮助说明我在某处发现的这个问题,我创建了一个小程序来重现这种现象.

I'm trying to understand how C allocates memory on stack. I always thought variables on stack could be depicted like structs member variables, they occupy successive, contiguous bytes block within the Stack. To help illustrate this issue I found somewhere, I created this small program which reproduced the phenomenon.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void function(int  *i) {
    int *_prev_int =  (int *) ((long unsigned int) i -  sizeof(int))  ;
    printf("%d\n", *_prev_int );    
}

void main(void) 
{
    int x = 152;
    int y = 234;
    function(&y);
}

看看我在做什么?假设sizeof(int)为4:我在传递的指针后面查找4个字节,因为它将在调用者的堆栈中的int y位置之前读取4个字节.

See what I'm doing? Suppose sizeof(int) is 4: I'm looking 4 bytes behind the passed pointer, as that would read the 4 bytes before where int y in the caller's stack.

它没有打印152.奇怪的是,当我查看接下来的4个字节时:

It did not print the 152. Strangely when I look at the next 4 bytes:

int *_prev_int =  (int *) ((long unsigned int) i +  sizeof(int))  ;

现在可以正常工作,在调用程序的堆栈中打印x中的所有内容.为什么x的地址比y的地址低?堆栈变量是否颠倒存储?

and now it works, prints whatever in x inside the caller's stack. Why x has a lower address than y? Are stack variables stored upside down?

推荐答案

堆栈组织完全未指定,并且是特定于实现的.实际上,它取决于很多编译器(甚至是其版本)和优化标志.

Stack organization is completely unspecified and is implementation specific. In practice, it depends a lot of the compiler (even of its version) and of optimization flags.

有些变量甚至不位于堆栈上(例如,因为它们只是保存在某些寄存器中,或者是因为编译器对其进行了优化(例如,通过内联,常量折叠等).)

Some variables don't even sit on the stack (e.g. because they are just kept inside some registers, or because the compiler optimized them -e.g. by inlining, constant folding, etc..).

顺便说一句,您可能有一些假设的C实现,它不使用任何堆栈(即使我无法命名此类实现).

BTW, you could have some hypothetical C implementation which does not use any stack (even if I cannot name such implementation).

要了解有关堆栈的更多信息:

To understand more about stacks:

熟悉计算机的架构& 指令集(例如 ABI ,然后...

Become familiar with your computer's architecture & instruction set (e.g. x86) & ABI, then ...

询问您的编译器以显示汇编器代码和/或某些中间编译器表示形式.如果使用 GCC ,请使用gcc -S -fverbose-asm编译一些简单的代码(在编译foo.s >),然后尝试几个优化级别(至少-O0-O1-O2 ....).也尝试使用-fdump-tree-all选项(它会转储数百个文件,这些文件显示了源代码的编译器的某些内部表示形式).请注意,GCC还提供了内置返回地址

ask your compiler to show the assembler code and/or some intermediate compiler representations. If using GCC, compile some simple code with gcc -S -fverbose-asm (to get assembler code foo.s when compiling foo.c) and try several optimization levels (at least -O0, -O1, -O2 ....). Try also the -fdump-tree-all option (it dumps hundred of files showing some internal representations of the compiler for your source code). Notice that GCC also provides return address builtins

阅读有关垃圾收集的Appel的旧论文可能比堆栈要快.分配,并了解垃圾收集技术(因为他们经常需要检查并可能更改调用堆栈框架内的某些指针).要了解有关GC的更多信息,请阅读 GC手​​册.

Read Appel's old paper on garbage collection can be faster than stack allocation, and understand garbage collection techniques (since they often need to inspect and possibly change some pointers inside call stack frames). To know more about GC, read the GC handbook.

可悲的是,我不知道可以在语言级别访问调用堆栈的低级语言(如C,D,Rust,C ++,Go等).这就是为什么很难为C编写垃圾收集器的原因(因为GC需要扫描调用堆栈指针)...但是请参见

Sadly, I know no low-level language (like C, D, Rust, C++, Go, ...) where the call stack is accessible at the language level. This is why coding a garbage collector for C is difficult (since GC-s need to scan the call stack pointers)... But see Boehm's conservative GC for a very practical and pragmatic solution.

这篇关于C堆栈变量是否反向存储?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆