这些局部变量的地址背后的基本原理是什么?

时间:2018-06-02 22:36:59

标签: c local-variables stackframe

我在玩游戏并查看内存中的局部变量。令我惊讶的是,我不明白为什么地址就是这样。

以下是示例程序

new_df.reset_index(drop=True, inplace=True)

>>> new_df.head()
   count  day_of_week  hour_of_day                               unit_id  \
0    1.0            4           18  7a1efb1d-d4c1-47e1-9320-ff5707eae91e   
1    0.0            4           19  7a1efb1d-d4c1-47e1-9320-ff5707eae91e   
2    0.0            4           20  7a1efb1d-d4c1-47e1-9320-ff5707eae91e   
3    0.0            4           21  7a1efb1d-d4c1-47e1-9320-ff5707eae91e   
4    0.0            4           22  7a1efb1d-d4c1-47e1-9320-ff5707eae91e   

                                          unit_label  week  year  
0  _TEMPORARILY_DISABLED_Jenn`s Favorite Destinat...    46  2015  
1  _TEMPORARILY_DISABLED_Jenn`s Favorite Destinat...    46  2015  
2  _TEMPORARILY_DISABLED_Jenn`s Favorite Destinat...    46  2015  
3  _TEMPORARILY_DISABLED_Jenn`s Favorite Destinat...    46  2015  
4  _TEMPORARILY_DISABLED_Jenn`s Favorite Destinat...    46  2015  

我希望堆栈帧按顺序成为所有这些变量。 在GDB中打印出来的内存地址显示情况并非如此!

 int main() {
   int my_array[30]; 
   int a = 10; 
   int b = 11; 
   char h = 'A'; 
   char temp_array[10];
   int c = 12; 
 }

基于这些内存地址,堆栈帧实际上是:

(gdb) print &my_array
$4 = (int (*)[30]) 0x7fffffffde10
(gdb) print &a
$5 = (int *) 0x7fffffffde04
(gdb) print &b
$6 = (int *) 0x7fffffffde08
(gdb) print &h
$7 = 0x7fffffffde03 '/' <repeats 13 times>
(gdb) print &temp_array
$8 = (char (*)[10]) 0x7fffffffde90
(gdb) print &c
$9 = (int *) 0x7fffffffde0c

为什么会这样?我假设我的编译器(gcc)出于某种原因以这种方式安排它,有人可以告诉我为什么吗?谢谢。 编辑:可能是字节对齐或什么?缓冲区首先是整数,然后是整数,然后是字符,那么为什么它会转到CBA而不是ABC呢?

1 个答案:

答案 0 :(得分:0)

  

为什么会这样?

编译器可以根据需要自由布局堆栈帧。此布局可以从版本更改为版本,从编译器更改为编译器,并具有不同的优化级别。

要知道正好选择此特定布局的原因,您必须在执行布局时逐步执行GCC。

一般来说,GCC可能会尝试最小化变量之间的漏洞/填充(当程序耗尽堆栈时,它会使最终用户感到恼火)。这可以解释为什么所有int变量都被分配在一起 - 它们具有相同的对齐要求,可以一个接一个地分配,没有间隙。