部分gcc预定义宏和函数栈帧的内存分布

news2025/1/20 20:07:43

本文简单基于树莓派8,linux4.4.50版本,32位arm cpu
尝试了解函数调用栈的内存分布的形态。使用gcc内置的宏 __builtin_frame_address 来打印栈帧内存上的信息,以及了解一下常用的gcc 内置的宏的输出。
针对 __builtin_frame_address 在gcc官网上可以看到更多的说明:
https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/getting-the-return-or-frame-address-of-a-function.html

1 预定义宏的输出

#include <stdio.h>

int call_func1(){
    printf("\n %s \n",__func__);
    printf("__func__ %s\n",__func__);
    printf("__LINE__ %d\n",__LINE__);
    printf("__FILE__ %s\n",__FILE__);
    printf("__DATE__ %s\n",__DATE__);
    printf("__time__ %s\n",__TIME__);
    printf("__func__ %s __builtin_frame_address %p\n",__func__,__builtin_frame_address(0));
    printf("__func__ %s,__builtin_return_address %p\n",__func__,__builtin_return_address(0));
}

int main(){
    call_func1();
    return 0;
}

上述源文件的输出如下:


 call_func1
__func__ call_func1 //函数名
__LINE__ 51         //行号
__FILE__ main.c     //源文件名
__DATE__ Nov 27 2022    //编译日期
__time__ 17:58:17           //编译时间
__func__ call_func1 __builtin_frame_address 0x7ec541a4
__func__ call_func1,__builtin_return_address 0x10794

__builtin_frame_address 表示函数的栈帧地址,__builtin_return_address表示函数的返回地址。

2 栈帧的内存打印

以如下形式的程序调用为例

#include <stdio.h>

int call_func2(int parm, int parm2){
    int i = 10;
    int j = 0;
    void * offset = NULL;

    printf("\n %s \n",__func__);

    /*打印从函数的栈帧开始 10个cpu地址(32位)的地址和值*/
    for (j = 0 ; j < i; j++){
        offset = __builtin_frame_address(0)- j*sizeof(int*);
        printf("__builtin_frame_address %p value [%x]\n",offset,*(int*)offset);
    }

    /*打印函数的返回地址 ,3个变量的地址,两个入参的地址*/
    printf("__builtin_return_address %p\n",__builtin_return_address(0));
    printf("first variable i  %p\n",&i);
    printf("second variable j  %p\n",&j);
    printf("third variable j  %p\n",&offset);
    printf("first parm parm   %p\n",&parm);
    printf("second parm parm   %p\n",&parm2);
    return 0;
}

int call_func1(){
    printf("__func__ %s __builtin_frame_address %p\n",__func__,__builtin_frame_address(0));
    printf("__func__ %s,__builtin_return_address %p\n",__func__,__builtin_return_address(0));
    call_func2();
    return 0;
}

int main(){
    call_func1();
    return 0;
}

上述的程序的调用流程是 main->call_func1->call_func2 。其中call_func1打印了函数的栈帧地址和返回地址,call_func2先后打印了其以帧地址为开始之后10个4字节内存的地址和内容,然后打印了函数的返回地址 ,3个变量的内存地址,两个入参的内存地址
其输出结果如下:

__func__ call_func1 __builtin_frame_address 0x7e8041a4
__func__ call_func1,__builtin_return_address 0x10810

 call_func2
__builtin_frame_address 0x7e985194 value [0x107cc]
__builtin_frame_address 0x7e985190 value [0x7e9851a4]
__builtin_frame_address 0x7e98518c value [0x10810]
__builtin_frame_address 0x7e985188 value [0x10a4c]
__builtin_frame_address 0x7e985184 value [0xa]
__builtin_frame_address 0x7e985180 value [0x5]
__builtin_frame_address 0x7e98517c value [0x7e98517c]
__builtin_frame_address 0x7e985178 value [0x76ffa000]
__builtin_frame_address 0x7e985174 value [0x4]
__builtin_frame_address 0x7e985170 value [0x1]
__builtin_return_address 0x107cc
first variable i  0x7e804184
second variable j  0x7e804180
third variable j  0x7e80417c
first parm parm   0x7e804174
second parm parm   0x7e804170

以内存地址的形式呈现,可以得到如下图:

在这里插入图片描述

栈帧的开始位置,其内容是是 0x107cc ,是函数的返回地址。即__builtin_return_address(0),下一个32位的内容是0x7e8041a4 ,根据其返回函数的打印,是返回后函数的栈帧开始位置。可以印证 栈是向下增长的,返回地址的栈在更高的地址。再下一个32位的内容是,0x10810,是其返回函数的返回地址。

再接下来一个32位的内容为空,或是任意值,该值可能为预留,使用gdb也未寻找到符号位置。

接下来三个32位均为栈上的变量的地址,i j 和offset。

再下一个值的内容为随机,其含义也不明。该32位可能也为预留值。

接下来两个地址为函数调用的局部变量的地址,parm和parm2

如果有更多的入参调用,会发现预留给参数变量的栈帧大小大约是 4*32 ,如果超过该范围,就会预先先进行调用参数的内存分配,再执行函数的栈上内存分配。即地址会在0x7e985194 栈帧地址之前。
在这种情况下,如果形参进行了越界的修改,就会导致栈帧上的返回地址被破坏,导致出现崩溃。该点可后续继续实验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

猴子也能学会的jQuery第十二期——jQuery遍历(上)

&#x1f4da;系列文章—目录&#x1f525; 猴子也能学会的jQuery第一期——什么是jQuery 猴子也能学会的jQuery第二期——引用jQuery 猴子也能学会的jQuery第三期——使用jQuery 猴子也能学会的jQuery第四期——jQuery选择器大全 猴子也能学会的jQuery第五期——jQuery样式操作…

PIC单片机3——外部中断

//RB2&#xff08;INT2&#xff09;作为外中断 #include <p18cxxx.h>/*18F系列单片机头文件*/ void PIC18F_High_isr(void);/*中断服务函数声明*/ void PIC18F_Low_isr(void); #pragma code high_vector_section0x8 /*高优先级中断响应时&#xff0c;会自动跳转到0x8处…

基于三相坐标系状态方程的感应电动机起动动态计算matlab程序

基于三相坐标系状态方程的感应电动机起动动态计算matlab程序 1 异步电动机动态数学模型的性质 电磁耦合是机电能量转换的必要条件&#xff0c;电流与磁通的乘积产生转矩&#xff0c;转速与磁通的乘积得到感应电动势。无论是直流电动机&#xff0c;还是交流电动机均如此。 交、直…

二十七、CANdelaStudio深入-编辑技巧(一致性检查)

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio软件的一致性检查,欢迎各位朋友订阅、评论…

『LeetCode|每日一题』---->最小路径和

目录 1.每日一句 2.作者简介 『LeetCode|每日一题』最小路径和 1.每日一题 2.解题思路 2.1 思路分析 2.2 核心代码 2.3 完整代码 2.4 运行结果 1.每日一句 希望冬天的风能吹散一年里所有的遗憾 2.作者简介 &#x1f3e1;个人主页&#xff1a;XiaoXiaoChen-2716 &#x1f…

Vue3框架中CompositionAPI的基本使用(第十课)

1.Setup函数 理解&#xff1a;Vue3.0中一个新的配置项&#xff0c;值为一个函数。 setup是所有Composition API&#xff08;组合API&#xff09;“ 表演的舞台 ”。 组件中所用到的&#xff1a;数据、方法等等&#xff0c;均要配置在setup中。 setup函数的两种返回值&#x…

kubernetes工作负载之控制器

目录 ​一、概述 二、Deployment 控制器 2.1Deployment 部署应用 2.2Deployment滚动升级 2.2.1应用部署完成 2.2.2更新镜像三种方式 2.3 Deployment 发布失败回滚 2.4Deployment 水平扩容 三、DaemonSet控制器 四、Job控制器 4.1Job一次性执行 4.2定时任务&#xf…

查询:按A分组,满足B时对应的C

1.场景 这种问题我自己归纳为“找对应行”问题&#xff0c;例如有下面一场表&#xff08;学生做题&#xff0c;对每个知识点的得分情况&#xff09; 字段&#xff1a;主键id、user_id、score、is_study、knowledgeName、updateTime场景1&#xff1a;按用户分组&#xff0c;求…

Nginx (7):nginx高可用配置

所谓的高可用&#xff0c;就是虽然nginx可以反向代理&#xff0c;如果某个内部服务器down了&#xff0c;可以使用其他的内部服务器&#xff0c;然而万一nginx挂了呢&#xff1f;&#xff1f;&#xff1f;&#xff1f;布置多个nginx再反向代理nginx&#xff1f;&#xff1f;反向…

数据结构学习笔记(V):树与二叉树

目录 1 树 1.1 树的定义和基本术语 1.定义 2.基本术语 1.2 树的性质 2 二叉树 2.1 二叉树的定义和基本术语 1.定义 2.特殊二叉树 2.2 二叉树性质 2.3 二叉树存储结构 1.顺序存储 2.链式存储 3 二叉树进阶 3.1 二叉树顺序遍历 1.先序遍历 2.中序遍历 3.后序遍…

第十二周总结

这周我来总结一下数论分块和佩尔方程&#xff1a; 已知正整数n&#xff0c;求&#xff0c;对n/i下取整&#xff0c;相当于把一组数分块了&#xff0c;首先我们来找一下规律&#xff1a;n20时 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 …

现代密码学导论-20-流密码

目录 3.6 实际操作和加密方式 3.6.1 流密码 CONSTRUCTION 3.30 使用伪随机函数构造流密码 3.6.2 流密码的同步模式 CONSTRUCTION 3.31 流密码的异步模式 3.6 实际操作和加密方式 现代密码学导论-14-基于伪随机发生器的EAV安全_南鸢北折的博客-CSDN博客 CONSTRUCTION 3.17…

Spring Cloud整合Nacos集群

目录 第一章 微服务架构图 第二章 Spring Cloud整合Nacos集群 第三章 Spring Cloud GateWay 第四章 Spring Cloud Alibaba 整合Sentinel 第五章 Spring Cloud Alibaba 整合SkyWalking链路跟踪 第六章 Spring Cloud Alibaba 整合Seata分布式事务 第七章 Spring Cloud 集成Auth用…

计量数据分析数据库-Stata分析包使用指南、计量分析资料等八大数据大全

一、计量前沿stata 分析包使用指南 当考虑自变量X对因变量Y的影响时&#xff0c;如果X通过影响变量M来影响Y,则称M为中介变量&#xff08;mediator或mediating variable) (Judd & Kenny, 1981; Baron &Kenny,1986)。X通过中介变量M对Y产生的影响就是中介效应&#xff…

【深入理解C++】可调用对象、std::function、std::bind()

文章目录1.可调用对象1.1 函数指针1.2 具有operator()成员函数的类对象/仿函数/函数对象1.3 可被转换为函数指针的类对象1.4 类成员函数指针2.std::function2.1 绑定普通函数2.2 绑定类的静态成员函数2.3 绑定具有operator()成员函数的类对象2.4 绑定可被转换为函数指针的类对象…

【无标题】SAR雷达系统反设计及典型目标建模与仿真实现研究——目标生成与检测(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

408考研科目《数据结构》第八章第一节:排序的基本概念和插入排序(直接插入排序,折半插入排序,希尔排序)

文章目录教程1.排序的基本概念1.1 排序算法的评价指标1.2 排序算法的分类2. 插入排序2.1 直接插入排序2.1.1 算法效率分析2.2 折半插入排序总结2.3 希尔排序 &#xff08;Shell Sort&#xff09;总结教程 排序&#xff1a; https://www.bilibili.com/video/BV1b7411N798/?p77…

队列——算法专项刷题(七)

七、队列 常用于辅助遍历树&#xff0c;设计队列先进先出特性的数据结构 7.1 滑动窗口的平均值 给定一个整数数据流和一个窗口大小&#xff0c;根据该滑动窗口的大小&#xff0c;计算滑动窗口里所有数字的平均值。 实现 MovingAverage 类&#xff1a; MovingAverage(int si…

图书管理系(附源码PPT)

图书管理系统1 绪 论1.1 研究背景1.2 研究意义1.3 相关研究现状1.3.1 高校图书管理面临的问题1.3.2 信息化为图书管理带来新变化2 相关技术2.1 JSP 概述2.2 MySQL 数据库技术2.3 Spring2.4 SpringMVC2.5 Dbcp2.6 Maven3 系统分析3.1 需求分析3.1.1 系统的功能需求分析3.1.2 系统…

利用衍射表面消色差的混合目镜建模

1. 摘要 同时具有折射和衍射表面的混合透镜已成为一种极具潜力的解决方案应用于多种领域。在此案例中&#xff0c;我们将演示混合目镜的一个例子&#xff0c;其中利用衍射透镜表面对色差进行了校正。由ZemaxOpticStudio进行初始化设计&#xff0c;并导入VirtualLab Fusion进行进…