- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
调用函数的栈帧可以通过__builtin_frame_address(1)
轻松获取,但是栈帧的大小呢?
是否有一个函数可以让我知道调用函数的堆栈帧有多大?
最佳答案
我的第一 react 是,为什么会有人想要这个?对于 C 函数来说,动态确定堆栈帧的大小应该被认为是不好的做法。 cdecl( 经典 C 调用约定)的全部意义在于函数本身(“被调用者”)不知道堆栈帧的大小。当切换到不同的平台、不同的地址大小(例如从 32 位到 64 位)、不同的编译器甚至不同的编译器设置(特别是优化)时,任何偏离该理念的行为都可能导致代码中断。
另一方面,由于 gcc 已经提供了这个函数 __builtin_frame_address
,看看从那里可以得到多少信息会很有趣。
来自documentation :
The frame address is normally the address of the first word pushed on to the stack by the function.
在 x86 上,函数通常以:
push ebp ; bp for 16-bit, ebp for 32-bit, rbp for 64-bit
换句话说,__builtin_frame_address
返回调用者堆栈帧的基指针。不幸的是,基指针很少或根本没有说明任何堆栈帧的开始或结束位置;基指针指向堆栈帧中间某处的位置(在参数和局部变量之间)。
如果你只对保存局部变量的栈帧部分感兴趣,那么函数本身就拥有所有的知识。该部分的大小是堆栈指针和基指针之间的差异。
register char * const basepointer asm("ebp");
register char * const stackpointer asm("esp");
size_localvars = basepointer - stackpointer;
请记住,gcc 似乎从一开始就在堆栈上分配空间,用于保存从被调用者内部调用的其他函数的参数。严格来说,那个空间属于那些其他函数的堆栈帧,但边界不明确。这是否是一个问题,取决于您的目的;您将如何处理计算出的栈帧大小?
至于另一部分(参数),则视情况而定。如果您的函数具有固定数量的参数,那么您可以简单地测量(形式)参数的大小。它不能保证调用者实际上将相同数量的参数压入堆栈,但假设调用者编译时没有针对被调用者的原型(prototype)发出警告,它应该没问题。
void callee(int a, int b, int c, int d)
{
size_params = sizeof d + (char *)&d - (char *)&a;
}
您可以结合这两种技术来获得完整的堆栈框架(包括返回地址和保存的基指针):
register char * const stackpointer asm("esp");
void callee(int a, int b, int c, int d)
{
total_size = sizeof d + (char *)&d - stackpointer;
}
但是,如果您的函数具有可变数量的参数(“省略号”,如 printf
具有),则只有调用者知道参数的大小。除非被调用者有办法导出参数的大小和数量(在 printf
风格的函数的情况下,通过分析格式字符串),否则您必须让调用者将该信息传递给被叫者。
编辑:请注意,这只适用于让一个函数测量他自己的堆栈框架。被调用者无法计算其调用者的栈帧大小;被调用者必须向调用者询问该信息。
但是,被调用者可以对调用者局部变量的大小进行有根据的猜测。此 block 从被调用者的参数结束处开始 (sizeof d + (char *)&d
),并在调用者的基指针 (__builtin_frame_address(1)
) 处结束。由于编译器强加的地址对齐,起始地址可能会稍微不准确;计算出的大小可能包括一 block 未使用的堆栈空间。
void callee(int a, int b, int c, int d)
{
size_localvars_of_caller = __builtin_frame_address(1) - sizeof d - (char *)&d;
}
关于c - 查找栈帧大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21501222/
栈一种常见的特殊线性数据结构,其特殊之处在于其操作顺序,下面会详细介绍,也正因为其特性,因此栈可以轻松解决表达式求值、括号匹配、递归算法、回溯算法等等问题。 01、定义 栈的特殊性表现为操作受
目录 实践1 —— 从字符串中移除星号 栈和数组存储数据的方式一样,它们都只是元素的列表。不同之处在于栈的以下3个限制: 数据只能从栈末插入; 数据只
准备工作 工具:idea+jdk8 技术要求:java基础语法 编码环节 首先,我们得先确定下来,用什么数据来模拟栈的操作。由于是一个一个的元素放入栈里面,我们可以考虑用数组来实现。
0. 学习目标 栈和队列是在程序设计中常见的数据类型,从数据结构的角度来讲,栈和队列也是线性表,是操作受限的线性表,它们的基本操作是线性表操作的子集,但从数据类型的角度来讲,它们与线性表又有着巨大的不
在可以使用递归(在堆栈中存储状态)和对象创建(在堆中创建新对象)的场景中。 问题 在对象创建和递归之间进行选择时应考虑哪些参数? 我的研究得出以下结论(需要验证这一点) 当可用内存较少时:使用递归 可
下面是我编写的用于检查内存对齐的示例程序。 Pavan@Pavan-pc:~/working_dir/pavan/C$ cat mem3.c #include #include
Instapaper 和 Twitterrific 等应用启动的 View 不是其导航堆栈的 Root View 。我们知道这一点,因为初始 View 已经有一个后退按钮。 Instapaper 推出
有没有办法在调试或正常运行期间的某个时刻可视化 Activity 堆栈? 最佳答案 您可以通过 Activity 管理器获取一些有用的信息。 ActivityManager manag
我想编写一个应用层协议(protocol),在发送 GET 请求时使用 TCP 返回特定的 ASCII 文本。我读了第一HTTP specification和 the SMTP specificati
1、堆和栈的速度性能分析 堆和栈是jvm内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内
一: 概念 栈,同样是一种特殊的线性表,是一种last in first out(lifo)的形式,现实中有很多这样的例子,
java中stack类继承于vector,其特性为后进先出(lastinfirstout). 入栈和出栈实例图: 实例图的java代码实例: ?
1、单链表 1、在我们数据结构中,单链表非常重要。它里面的数据元素是以结点为单位,每个结点是由数据元素的数据和下一个结点的地址组成,在java集合框架里面 LinkedList、Ha
本文实例讲述了Python编程实现双链表,栈,队列及二叉树的方法。分享给大家供大家参考,具体如下: 1.双链表 ?
我一遍又一遍地阅读定义,但我仍然不明白ARM中的SP和LR是什么?我了解PC(它显示下一条指令的地址),SP和LR可能类似,但我只是不明白它是什么。你能帮我一下吗? 编辑:如果你能用例子来解释它,那就
我必须使用索引 0 作为堆栈的顶部,并且在实现此操作时遇到问题。我得到了所有 null,但输出 100、200 和 300 是我得到的唯一数字。我忽略的实现有什么问题吗? push 方法应该实现 Ar
我正在用 Java 解决汉诺塔问题。我选择使用 Stacks 作为钉子,除了 move 方法之外,一切都正常。我有规范和 JUnit 测试类,目前通过了 7 项测试中的 6 项,但在移动测试中失败了。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Does this type of memory get allocated on the heap or
首先,抱歉我的英语不好。我将尝试解释我的问题: 我有一个 RootViewController(基于导航的项目)。因此,它显示了表格 View ,当用户选择表格的一行 (didSelectRowAtI
我有一个看起来像这样的类 class A { int b; void B() { int c; } } int main() { A asdf;
我是一名优秀的程序员,十分优秀!