Windows 7 64 位中的递归

2023-12-26

我有这个助手类

public static class DateTimeHelper
  {
    public static int GetMonthDiffrence(DateTime date1, DateTime date2)
    {
      if (date1 > date2)
      {
        return getmonthdiffrence(date2, date1);
      }
      else
      {
        return ((date2.year - date1.year) * 12) + (date2.month - date1.month);
      }      
    }
  }

该函数计算两个日期之间的月数,它正是我想要的。 到目前为止还没有问题。

问题是当我在发行版和 Windows 7 64 位上时,我总是得到相同的值“0”

当我深入研究这个问题时,我意识到在某个时刻,由于递归调用,两个参数是相等的。

我再说一遍,只有当我在 Windows 7 64 位上运行未附加到调试器的版本时,才会出现此错误。

任何人都可以了解这种行为吗?如果是这样,我需要一些链接来了解更多详细信息。

这是 IL 代码。 (我认为这可以帮助理解更多)

.class public auto ansi abstract sealed beforefieldinit Helpers.DateTimeHelper
    extends [mscorlib]System.Object
{
    // Methods
    .method public hidebysig static 
        int32 GetMonthDiffrence (
            valuetype [mscorlib]System.DateTime date1,
            valuetype [mscorlib]System.DateTime date2
        ) cil managed 
    {
        // Method begins at RVA 0x6a658
        // Code size 52 (0x34)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldarg.1
        IL_0002: call bool [mscorlib]System.DateTime::op_GreaterThan(valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
        IL_0007: brfalse.s IL_0011

        IL_0009: ldarg.1
        IL_000a: ldarg.0
        IL_000b: call int32 Helpers.DateTimeHelper::GetMonthDiffrence(valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
        IL_0010: ret

        IL_0011: ldarga.s date2
        IL_0013: call instance int32 [mscorlib]System.DateTime::get_Year()
        IL_0018: ldarga.s date1
        IL_001a: call instance int32 [mscorlib]System.DateTime::get_Year()
        IL_001f: sub
        IL_0020: ldc.i4.s 12
        IL_0022: mul
        IL_0023: ldarga.s date2
        IL_0025: call instance int32 [mscorlib]System.DateTime::get_Month()
        IL_002a: ldarga.s date1
        IL_002c: call instance int32 [mscorlib]System.DateTime::get_Month()
        IL_0031: sub
        IL_0032: add
        IL_0033: ret
    } // end of method DateTimeHelper::GetMonthDiffrence
} 

EDIT:

如果您想重现该问题,这里有一个测试程序:

class Program
  {
    static void Main(string[] args)
    {
      for (int i = 2000; i < 3000; i++)
      {
        var date1 = new DateTime(i, 1, 1);
        var date2 = new DateTime(i + 1, 1, 1);
        var monthdiff = DateTimeHelper.GetMonthDiffrence(date2, date1);
        if (monthdiff == 0)
          Console.WriteLine(string.Format("date1 => {0}, date2 => {1}, diff=> {2}", date2, date1, monthdiff.ToString()));
      }
      Console.WriteLine("done!");
      Console.ReadKey();
    }
  }

您必须在发布模式和 64 位配置上构建项目,然后转到构建结果的位置并执行程序。 预先感谢。 我最诚挚的问候。


我可以在 Windows 7、.Net 4.5、Visual Studio 2012、x64 目标、附加调试器的发布模式上复制此行为,但禁用“抑制模块加载时的 JIT 优化”。这似乎是尾部调用优化中的一个错误(这就是为什么你只能在 x64 上获得它)。

IL在这里并不重要,重要的是本机代码。代码的相关部分GetMonthDiffrence() is:

0000005e  cmp         rdx,rcx 
00000061  setg        al 
00000064  movzx       eax,al 
00000067  test        eax,eax 
00000069  je          0000000000000081 // else branch
0000006b  mov         rax,qword ptr [rsp+68h] 
00000070  mov         qword ptr [rsp+60h],rax 
00000075  mov         rax,qword ptr [rsp+60h] 
0000007a  mov         qword ptr [rsp+68h],rax 
0000007f  jmp         0000000000000012 // start of the method

重要的部分是4mov指示。他们尝试着交换[rsp+68h] and [rsp+60h](这是参数存储的位置),但它们做得不正确,因此两者最终得到相同的值。

有趣的是,如果我删除对Console.ReadKey()从你的Main(),代码工作正常,因为调用GetMonthDiffrence()是内联的,在这种情况下不会执行尾部调用优化。

一个可能的解决方法是添加[MethodImpl(MethodImplOptions.NoInlining)]对于您的方法,这似乎禁用了尾部调用优化。

I have 在 Connect 上提交了此错误 https://connect.microsoft.com/VisualStudio/feedback/details/792660/tail-call-optimization-doesnt-switch-parameters-correctly.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows 7 64 位中的递归 的相关文章

  • Grpc - 将消息从一个客户端发送到连接到同一服务器的另一个客户端

    是否可以将消息从一个客户端发送到连接到同一服务器的另一个客户端 我想将数据从一个客户端发送到服务器然后发送到特定客户端 我想我需要获取客户端 ID 但我不知道如何获取此 ID 以及如何从服务器将此消息发送到该客户端 我这里有一个样本 这是一
  • 如何在类文件中使用 Url.Action() ?

    如何在 MVC 项目的类文件中使用 Url Action Like namespace 3harf public class myFunction public static void CheckUserAdminPanelPermissi
  • 前向声明类型和“已声明为类类型的非类类型”

    我对以下代码有问题 template
  • 从复选框列表中选择循环生成的复选框中的一个复选框

    抱歉我的英语不好 在我的 ASP NET 网站上 我从 SQL 表导入软件列表 看起来像这样 但实际上要长得多 Microsoft Application Error Reporting br br Microsoft Applicatio
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • 有些有助于理解“产量”

    在我不断追求少吸的过程中 我试图理解 产量 的说法 但我不断遇到同样的错误 someMethod 的主体不能是迭代器块 因为 System Collections Generic List 不是迭代器接口类型 这是我被卡住的代码 forea
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 如何将 .txt 文件中的数据转换为 xml? C#

    我在一个文本文件中有数千行数据 我想通过将其转换为更容易搜索的内容来轻松搜索 我希望 XML 或其他类型的大型数据结构 尽管我不确定它是否是最好的对于我的想法 每行的数据如下所示 第 31 册 托马斯 乔治 32 34 154 每本书都不是
  • Task.Run 作为反模式?

    我正在将 SQLite NET PCL 库用于我的 WinRT 项目SQliteAsyncConnection类 它提供经典的异步版本SQLiteConnection方法 然而 就该项目而言Github页面 https github com
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 从 C# 使用 Odbc 调用 Oracle 包函数

    我在 Oracle 包中定义了一个函数 CREATE OR REPLACE PACKAGE BODY TESTUSER TESTPKG as FUNCTION testfunc n IN NUMBER RETURN NUMBER as be
  • 将 Word 转换为 PDF - 禁用“保存”对话框

    我有一个用 C 编写的 Word 到 PDF 转换器 除了一件事之外 它工作得很好 有时 在某些 Word 文件上 后台会出现一条消息保存源文件中的更改 gt 是 否 取消 但我没有对源文件进行任何更改 我只想从 Word 文件创建 PDF
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • Visual Studio 2015:v120 与 v140?

    仅供参考 Win10 x64 我今天开始尝试 Visual Studio 2015 在弄清楚如何运行 C C 部分后 我尝试加载一个大型个人项目 该项目使用非官方的glsdk http glsdk sourceforge net docs
  • 为什么 0.5 mod 0.1 在不同的编程语言中结果不同?

    我有一个关于模数的问题 模运算求一个数除以另一个数的余数 我原本期望 0 5 0 1 0 的结果 但是当我在 PHP 或 net 中运行它时 我得到 0 1 我运行的 php 代码是 var dump fmod 0 5 0 1 在 net中
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include

随机推荐

  • Typescript 与“typeof”相反/反向操作

    Angular 可以按类型查询子组件 在测试中使用它 如下所示 fixture debugElement query By directive ComponentType 现在我想创建一个为我执行此操作的函数 import Componen
  • 从其他类 Objective-C 访问方法

    寻找这个问题的答案 但我还没有找到合适的答案 我希望你们 和女孩 能帮助我 这是针对 iPhone 应用程序的 好吧 我有一个多视图应用程序 每个视图都有自己的类 一切都很愉快 然而 不同的类有时会调用相同的方法 到目前为止 我只是在两个类
  • 尝试批量插入行时发生 Knexjs 错误:获取连接超时。泳池可能已经满了。

    完整错误 Knex 获取连接超时 池可能已满 您是否缺少 transacting trx 调用 我有一个超过 70k 行的 csv json 插入 15k 17k 次后 它停止并抛出上述错误 代码如下 csvtojson colParser
  • Microsoft Graph API 是否支持 Azure AD B2C 的更改通知?

    我正在尝试获取更改通知 以便用户使用连接到 Azure AD B2C 的应用程序 我按照以下教程操作并成功创建了订阅 但我从未收到任何更改通知 https learn microsoft com en us learn modules ms
  • 如何存储长符号计算的结果以供以后使用?

    我的计算是这样的 f x runs fast g x runs fast h x depends on f x g x runs slow 5mins 现在我只需要结果h x 每次我重新启动 mma 时 我基本上都会重做相同的计算以获得h
  • 将 JSON 转换为 .NET 数据集

    我正在编写一个 Java servlet 它使用http json org java http json org java 用于从 mssql 数据库读取一些数据并将结果集转换为 JSON 字符串的库 NET 客户端应用程序正在使用此 JS
  • 如何在Word宏中的TextBox中插入文本

    我在Word中创建了一个文本框 我想在其中插入文本 Sub k Dim Box As Shape Set Box ActiveDocument Shapes AddTextbox Orientation msoTextOrientation
  • 如何在谷歌地图 API v3 中一次仅显示一个信息窗口

    我们可以在谷歌地图中一次仅显示一个信息窗口 并为多个标记显示多个信息窗口吗 意味着 当我单击标记时隐藏 关闭其他信息窗口并仅显示当前标记信息窗口 Thanks 我解决的方法如下 var infoWindowsOpenCurrently A
  • C# 在方法或事件处理程序之间传递变量

    我仍在尝试学习 c 我的问题是如何将变量从 Item1 Click 传递到 Item2 Click 这与在方法之间传递它们是同一件事还是因为它们是事件处理程序而有所不同 public partial class Events System
  • K&R 第 2 版,示例 1.9 字符数组

    我对以下代码中的 getline 函数和参数定义有疑问 代码直接取自 K R 第 1 9 章 字符数组 我已将其逐字复制在这里 问题是 当我按原样编译程序时 出现三个错误 我在最后重现了这些错误 当我在出现错误的三个地方将函数和函数参数定义
  • 从 sql 修改 SSIS 目录中的连接管理器信息

    有没有办法在使用 sql 代码部署后从 ssis 目录更新连接管理器信息 我想先部署没有敏感数据的项目 执行目录 deploy project 然后通过 SQL 将用户名和密码添加到 SSIS 目录项目 有没有办法从以下位置更新连接管理器信
  • 空间域图像卷积

    我正在尝试复制结果这个链接 https stackoverflow com q 38709810 159072 using linear卷积于空间域 图像首先转换为二维double数组 然后进行卷积 图像和内核大小相同 图像在卷积之前进行填
  • 加快用最后一个非 Nan 值替换 NaN

    我想用最后一个非 NaN 值替换向量中的所有 NaN input 1 2 3 NaN NaN 2 output 1 2 3 3 3 2 我想尝试加快已有的循环速度 input 1 2 3 NaN NaN 2 if isnan input 1
  • 单击 Angular 网页中的 TableRow 时出现 StaleElementException

    div class row gridrow clickable ng scope i class col m1 s1 tiny fa fa male i div class col m3 s11 ng binding Allard div
  • 如何删除MySQL中的记录并保留最新日期

    Example table 1 ID Email Answer UpdateDate 1 email protected cdn cgi l email protection 1 2011 07 02 2 email protected c
  • Webpack 错误:configuration.module.rules[0] 有一个未知的属性“query”

    我正在关注这个教程 https www youtube com watch v iWUR04B42Hc https www youtube com watch v iWUR04B42Hc 我知道它的内容已过时 但我认为已将其正确翻译为最新版
  • ASP.Net 移动 Web 表单发生了什么?

    以前 Visual Studio 具有用于移动 Web 表单 而不是移动 SDK 的模板 它们似乎在 Visual Studio 2008 中消失了 我见过的唯一解决方案是从 Omar 下载一些模板 http blogs msdn com
  • Pandas hub_table,按列对值进行排序

    我是 Pandas 的新用户 我喜欢它 我正在尝试在 Pandas 中创建一个数据透视表 一旦我按照我想要的方式获得了数据透视表 我想按列对值进行排名 我附上了 Excel 中的图像 因为以表格格式更容易看到我想要实现的目标 链接到图像 h
  • 找到使图像在列表中唯一的像素,您可以改进暴力破解吗?

    假设我有一个字符串列表 其中每个字符串是 正好 4 个字符长并且 在列表中是唯一的 对于每个字符串 我想确定字符串中使该字符串唯一的字符的位置 所以对于三个字符串的列表 abcd abcc bbcb 对于第一个字符串 我想识别第四个位置的字
  • Windows 7 64 位中的递归

    我有这个助手类 public static class DateTimeHelper public static int GetMonthDiffrence DateTime date1 DateTime date2 if date1 gt