《coredump问题原理探究》Linux x86版5.7节C风格数据结构内存布局之结构体数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/details/8836763

在探究过数组和结构体这两种非原生的数据类型之后,可能会想知道这两种类型结合成结构体数组,会有什么特征。

先看一个例子:

  #include <stdlib.h>
  struct xuzhina_dump_c05_s3_3
  {
      short idx;
      int sq;
  };
  
  void init( struct xuzhina_dump_c05_s3_3* test, int n )
 {
     for ( int i = 0; i < n; i++ )
     {
         test[i].idx = i;
         test[i].sq = i*i;
     }
 }
 
 int sum( struct xuzhina_dump_c05_s3_3* test, int n )
 {
     int sum = 0;
     for ( int i = 0; i < n; i++ )
     {
         sum += test[i].sq;
     }
     return sum;
 }
 
 int main(int argc, char* argv[] )
 {
     if ( argc < 2 )
     {
         return 1;
     }

     int num = atoi( argv[1] );

     struct xuzhina_dump_c05_s3_3* test =
         (struct xuzhina_dump_c05_s3_3*)malloc( num * sizeof( struct xuzhina_dump_c05_s3_3 ) );
 
     init( test, num );
 
     return sum( test, num );
 }

汇编(只看init和sum即可)

(gdb) disassemble init
Dump of assembler code for function _Z4initP21xuzhina_dump_c05_s3_3i:
   0x080484d0 <+0>:     push   %ebp
   0x080484d1 <+1>:     mov    %esp,%ebp
   0x080484d3 <+3>:     sub    $0x10,%esp
   0x080484d6 <+6>:     movl   $0x0,-0x4(%ebp)		;i
   0x080484dd <+13>:    jmp    0x8048511 <_Z4initP21xuzhina_dump_c05_s3_3i+65>

   0x080484df <+15>:    mov    -0x4(%ebp),%eax
   0x080484e2 <+18>:    lea    0x0(,%eax,8),%edx		;edx = i*8
   0x080484e9 <+25>:    mov    0x8(%ebp),%eax		;eax = test
   0x080484ec <+28>:    add    %eax,%edx				;edx = test[i]
   0x080484ee <+30>:    mov    -0x4(%ebp),%eax		;i
   0x080484f1 <+33>:    mov    %ax,(%edx)			;test[i].idx = i
   0x080484f4 <+36>:    mov    -0x4(%ebp),%eax		;i
   0x080484f7 <+39>:    lea    0x0(,%eax,8),%edx		;edx = i*8
   0x080484fe <+46>:    mov    0x8(%ebp),%eax		;eax = test
   0x08048501 <+49>:    add    %eax,%edx				;edx = test[i]
   0x08048503 <+51>:    mov    -0x4(%ebp),%eax		;eax = i
   0x08048506 <+54>:    imul   -0x4(%ebp),%eax		;eax *= i
   0x0804850a <+58>:    mov    %eax,0x4(%edx)		;test[i].sq = eax
   0x0804850d <+61>:    addl   $0x1,-0x4(%ebp)			;i++
   0x08048511 <+65>:    mov    -0x4(%ebp),%eax
   0x08048514 <+68>:    cmp    0xc(%ebp),%eax
   0x08048517 <+71>:    setl   %al
   0x0804851a <+74>:    test   %al,%al
   0x0804851c <+76>:    jne    0x80484df <_Z4initP21xuzhina_dump_c05_s3_3i+15>

   0x0804851e <+78>:    leave  
   0x0804851f <+79>:    ret    
End of assembler dump.

(gdb) disassemble sum
Dump of assembler code for function _Z3sumP21xuzhina_dump_c05_s3_3i:
   0x08048520 <+0>:     push   %ebp
   0x08048521 <+1>:     mov    %esp,%ebp
   0x08048523 <+3>:     sub    $0x10,%esp
   0x08048526 <+6>:     movl   $0x0,-0x4(%ebp)		;sum
   0x0804852d <+13>:    movl   $0x0,-0x8(%ebp)		;i
   0x08048534 <+20>:    jmp    0x804854f <_Z3sumP21xuzhina_dump_c05_s3_3i+47>

   0x08048536 <+22>:    mov    -0x8(%ebp),%eax		;i
   0x08048539 <+25>:    lea    0x0(,%eax,8),%edx
   0x08048540 <+32>:    mov    0x8(%ebp),%eax		;test
   0x08048543 <+35>:    add    %edx,%eax
   0x08048545 <+37>:    mov    0x4(%eax),%eax		;test[i].sq
   0x08048548 <+40>:    add    %eax,-0x4(%ebp)
   0x0804854b <+43>:    addl   $0x1,-0x8(%ebp)			;i++
   0x0804854f <+47>:    mov    -0x8(%ebp),%eax
   0x08048552 <+50>:    cmp    0xc(%ebp),%eax		;i < n 
   0x08048555 <+53>:    setl   %al
   0x08048558 <+56>:    test   %al,%al
   0x0804855a <+58>:    jne    0x8048536 <_Z3sumP21xuzhina_dump_c05_s3_3i+22>

   0x0804855c <+60>:    mov    -0x4(%ebp),%eax
   0x0804855f <+63>:    leave  
   0x08048560 <+64>:    ret    
End of assembler dump.

从上面的汇编,结构体数组的特征如下:

1.        先是找到数组的首地址

2.        再根据索引找到每个元素,得到每个元素的地址。

3.        再以每个元素的地址作为结构体基址,再获取成员变量的地址。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Redis源码学习系列

Redis源码学习之字典

在字典结构体中,包含了一组字典函数(dictType),通过封装的方法处理对应的操作,通常在字典初始化的时候对其进行配置。

3401
来自专栏精讲JAVA

8 张图理解 Java

一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有最多的票选。如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟。

931
来自专栏java思维导图

8张图理解Java,一图胜千言

一图胜千言,下面图解均来自Program Creek 网站。如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟。 1、字符串不变性 下面这张图展示了这段代码...

2473
来自专栏申龙斌的程序人生

Eclipse油藏模型解析程序

2010年的时候,三维可视化项目中要读取eclipse建模软件产生的三维模型网格数据,经过连续多天的奋战,终于搞明白eclipse数模软件输出的egrid、in...

3317
来自专栏灯塔大数据

每周学点大数据 | No.23 外排序(二)

No.23期 外排序(二) Mr. 王:接下来我们用一个例子对磁盘归并排序进行说明。先来约定讨论的参数:N=24,M=8,B=2。 小可:嗯,一共有2...

3476
来自专栏对角另一面

lodash源码分析之数组的差集

本文为读 lodash 源码的第十七篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

1324
来自专栏开发与安全

从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)

首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(me...

2280
来自专栏运维小白

linux基础(day28)

9.6 awk(上) awk工具 head -n2 test.txt|awk -F ':' '{print $1}' head -n2 test.txt|awk...

2156
来自专栏数据结构与算法

P1965 转圈游戏

题目描述 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号小伙伴在第 0 号位置,第 ...

3808
来自专栏祥子的故事

Python编程快速上手 让繁琐工作自动化 | 第三章 :实践项目

3126

扫码关注云+社区

领取腾讯云代金券