- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在为我的C#应用程序开发一种自动日志机制。
这是我想要的样子:
function a(arg1, arg2, arg 3.....)
调用函数b(arg4,arg5,arg6....)
,该函数依次调用log()
,该Environment.StackTrace
能够检测stacktrace(可以通过a
完成)以及调用stacktrace中每个函数的值(例如b
和ojit_code)。
我希望它在调试和 Release模式下工作(或至少在 Debug模式下工作)。
可以在.net中执行此操作吗?
最佳答案
可能是不可能的:
到b
调用时,a的arg1
使用的堆栈中的空间(IL堆栈,因此可能甚至从未放入堆栈中,但已在调用中注册),不能保证arg1
仍在使用该空间。
通过扩展,如果arg1
是引用类型,则不能保证所引用的对象没有被垃圾回收(如果在调用b
之后未使用该对象)。
编辑:
稍微多一点,因为您的评论表明您并没有在意这点,但仍然认为应该可行。
规范中没有为任何相关标准指定抖动使用的调用约定,这使实现者可以自由地进行改进。实际上,它们在32位和64位版本以及不同的发行版之间确实有所不同。
但是,来自MS人士的文章建议使用的约定类似于__fastcall约定。在您对a
的调用中,将arg1
放入ECX寄存器*,并将arg2
放入EDX寄存器(我假设32位x86进行了简化,其中注册了amd64,甚至更多的参数)正在运行代码的核心。 arg3
将被压入堆栈,并且确实存在于内存中。
请注意,此时,arg1
和arg2
不存在内存位置,它们仅在CPU寄存器中。
在执行方法本身的过程中,必要时使用寄存器和存储器。然后b
被调用。
现在,如果a
将需要arg1
或arg2
,则必须在调用b
之前将其推送。但是,如果没有,那么就不会-甚至可能会重新排序以减少这种需求。相反,到目前为止,这些寄存器可能已经被用于其他用途-抖动并不愚蠢,因此,如果它需要一个寄存器或堆栈上的一个插槽,而其余的方法都没有使用,那就是重用该空间。 (为此,在此之上的级别,C#编译器将重用IL生成的虚拟堆栈中的插槽)。
因此,当调用b
时,arg4
放置在寄存器ECX中,arg5
放入EDX中,arg6
压入堆栈。在这一点上,arg1
和arg2
不存在,您再也无法找出它们的含义,因此,在将书回收并变成卫生纸后,您可以再读一本书。
(有趣的是,一种方法在相同位置调用另一个具有相同参数的方法是很普遍的,在这种情况下,可以不理会ECX和EDX)。
然后,b
返回,将其返回值放在EAX寄存器或EDX:EAX对中,或在EAX指向它的内存中,根据大小,a
在将返回值放入该寄存器之前还要做更多的工作,依此类推。
现在,这假设尚未进行任何优化。实际上,有可能根本没有调用b
,而是内联了它的代码。在这种情况下,值是在寄存器中还是在堆栈中-在后者的情况下,它们在堆栈中的位置都不再与b
的签名有关,而与a
期间的相关值无关的执行,并且在另一个“调用”到b
的情况下,甚至在另一个“调用”从b
到a
的情况下,都会有所不同,因为整个a
调用(包括其对b
的调用)都可以被内联在一种情况下,没有内联,而在另一种情况下又内联。例如,如果arg4
直接来自另一个调用返回的值,则此刻可能在EAX寄存器中,而arg5
在ECX中,因为它与arg1
相同,而arg6
在中间的中间a
使用的堆栈空间。
另一种可能性是,对b
的调用是一个尾部调用,因此被消除了:因为对b
的调用也将立即由a
(或其他可能性)立即返回其返回值,所以,而不是将其压入堆栈,替换a
使用的值,并更改返回地址,以便从b
返回的内容跳回到称为a
的方法,从而跳过了一些工作(并在某种程度上减少了内存使用,因为某些功能样式接近会使堆栈溢出,而确实可以很好地工作)。在这种情况下,在对b
的调用期间,对a
的参数可能已经完全消失,即使那些已经在堆栈中的参数也是如此。
最后一种情况是否甚至应该被认为是最优化是值得商highly的。一些语言在很大程度上依赖于它的完成,因为它们提供了良好的性能,即使它们完全可以工作,也不会给它们带来可怕的性能(而不是使堆栈溢出)。
可以有其他各种优化方式。 应该是的所有其他优化方式-如果.NET团队或Mono团队所做的事情使我的代码更快或使用的内存更少,但在没有其他要求的情况下却表现相同,我将一无所获提示!
并假设首先编写C#的人员从未更改过参数的值,这肯定不是正确的。考虑以下代码:
IEnumerable<T> RepeatedlyInvoke(Func<T> factory, int count)
{
if(count < 0)
throw new ArgumentOutOfRangeException();
while(count-- != 0)
yield return factory();
}
count
调用中已经存在了什么
factory
呢?即使在第一次调用时,它也是不同的,并且并非上面的代码是奇怪的代码。
arg1
是什么呢?
arg1
。如果这是对堆上对象的引用,那么它可能仍然对我们没有好处,因为如果以上所有内容都意味着堆栈上没有更多的引用处于 Activity 状态,那么很明显这确实会发生-并且GC启动,那么该对象可能已被收集。因此,我们可以神奇地掌握的是对不再存在的内容的引用-实际上很可能是对堆中现在用于其他用途的区域的支持,bang整个框架的整个类型安全!
MethodBody
,则通常内联的调用是无关紧要的。 this
是实例成员的真正第一个参数。让我们假装一切都是静态的,所以我们不必一直指出这一点。
关于c# - 有什么方法可以告诉在C#中调用函数的方法的参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12116429/
简而言之:我想从可变参数模板参数中提取各种选项,但不仅通过标签而且通过那些参数的索引,这些参数是未知的 标签。我喜欢 boost 中的方法(例如 heap 或 lockfree 策略),但想让它与 S
我可以对单元格中的 excel IF 语句提供一些帮助吗? 它在做什么? 对“BaselineAmount”进行了哪些评估? =IF(BaselineAmount, (Variance/Baselin
我正在使用以下方法: public async Task Save(Foo foo,out int param) { ....... MySqlParameter prmparamID
我正在使用 CodeGear RAD Studio IDE。 为了使用命令行参数测试我的应用程序,我多次使用了“运行 -> 参数”菜单中的“参数”字段。 但是每次我给它提供一个新值时,它都无法从“下拉
我已经为信用卡类编写了一些代码,粘贴在下面。我有一个接受上述变量的构造函数,并且正在研究一些方法将这些变量格式化为字符串,以便最终输出将类似于 号码:1234 5678 9012 3456 截止日期:
MySql IN 参数 - 在存储过程中使用时,VarChar IN 参数 val 是否需要单引号? 我已经像平常一样创建了经典 ASP 代码,但我没有更新该列。 我需要引用 VarChar 参数吗?
给出了下面的开始,但似乎不知道如何完成它。本质上,如果我调用 myTest([one, Two, Three], 2); 它应该返回元素 third。必须使用for循环来找到我的解决方案。 funct
将 1113355579999 作为参数传递时,该值在函数内部变为 959050335。 调用(main.c): printf("%d\n", FindCommonDigit(111335557999
这个问题在这里已经有了答案: Is Java "pass-by-reference" or "pass-by-value"? (92 个回答) 关闭9年前。 public class StackOve
我真的很困惑,当像 1 == scanf("%lg", &entry) 交换为 scanf("%lg", &entry) == 1 没有区别。我的实验书上说的是前者,而我觉得后者是可以理解的。 1 =
我正在尝试使用调用 SetupDiGetDeviceRegistryProperty 的函数使用德尔福 7。该调用来自示例函数 SetupEnumAvailableComPorts .它看起来像这样:
我需要在现有项目上实现一些事件的显示。我无法更改数据库结构。 在我的 Controller 中,我(从 ajax 请求)传递了一个时间戳,并且我需要显示之前的 8 个事件。因此,如果时间戳是(转换后)
rails 新手。按照多态关联的教程,我遇到了这个以在create 和destroy 中设置@client。 @client = Client.find(params[:client_id] || p
通过将 VM 参数设置为 -Xmx1024m,我能够通过 Eclipse 运行 Java 程序-Xms256M。现在我想通过 Windows 中的 .bat 文件运行相同的 Java 程序 (jar)
我有一个 Delphi DLL,它在被 Delphi 应用程序调用时工作并导出声明为的方法: Procedure ProduceOutput(request,inputs:widestring; va
浏览完文档和示例后,我还没有弄清楚 schema.yaml 文件中的参数到底用在哪里。 在此处使用 AWS 代码示例:https://github.com/aws-samples/aws-proton
程序参数: procedure get_user_profile ( i_attuid in ras_user.attuid%type, i_data_group in data_g
我有一个字符串作为参数传递给我的存储过程。 dim AgentString as String = " 'test1', 'test2', 'test3' " 我想在 IN 中使用该参数声明。 AND
这个问题已经有答案了: When should I use "this" in a class? (17 个回答) 已关闭 6 年前。 我运行了一些java代码,我看到了一些我不太明白的东西。为什么下
我输入 scroll(0,10,200,10);但是当它运行时,它会传递字符串“xxpos”或“yypos”,我确实在没有撇号的情况下尝试过,但它就是行不通。 scroll = function(xp
我是一名优秀的程序员,十分优秀!