【问题标题】:How to fix StackOverFlowException in .NET如何在 .NET 中修复 StackOverFlowException
【发布时间】:2016-12-24 13:37:09
【问题描述】:

ASP .NET 4.6 MVC 控制器在运行时创建 Razor 模板并使用 RazorEngine 运行它。
一个大模板在从 Visual Studio 运行时会导致 Stack Overflow 异常,或者在从 Mono 运行时会导致 Method CompiledRazorTemplates.Dynamic.dbcfcaeeb:Execute () is too complex.

如果从模板中删除大量 div,它会编译并运行正常。

如何解决这个问题?如何增加网络堆栈大小或任何其他想法?

导致此问题的 Razor 模板有 2880 行。它包含 228 个变量和大量 div:

@inherits Reporting.ReportTemplateBase<MYApp.ViewModels.RazorViewModel>

<!DOCTYPE html>
<html>
....
<body>
    @{
    dynamic Vrapopref=ko.Keel;
dynamic Vymardada=Iif(Ko.Ymardus==1,2,Iif(Ko.Ymardus==2,0,1));
dynamic Vjag=Iif(Ko.Ymardus!=3,1,1000);
dynamic V4gr= true ;
dynamic Vs41gr=0;
dynamic Vs42gr=0;
...
dynamic _calculated229=Round(Vs52gr/Vjag*Iif(Core.Left(r.BilskeemKontoklass,1)=="K",-1,1),Vymardada);
_calculated229=SetDefault(_calculated229);

    }


<div class='row' style='min-height:0.45cm'>
<div class='field' style='@TextBox(0.00,0.66,7.37,0.45);font-family:"Arial";font-weight:bold;'>@{try{WriteLiteral(Out(Eeva.Business.Prpalk.GetSfirmanimi()));} catch (Exception ex) {LogiVormiViga("Out(Eeva.Business.Prpalk.GetSfirmanimi())",ex);} }</div>

</div>
<div class='row' style='min-height:0.03cm'>
<div class='field' style='@TextBox(0.00,1.87,2.39,0.45);font-family:"Arial";font-size:9pt;'>@{try{WriteLiteral(Out(Ise.Regnr));} catch (Exception ex) {LogiVormiViga("Out(Ise.Regnr)",ex);} }</div>

</div>
<div class='row' style='min-height:0.42cm'>
<div class='field' style='left:0.66cm;font-family:"Arial";font-size:9pt;'>@Raw(IR("Reg nr"))</div>

</div>
<div class='row' style='min-height:0.71cm'>
<div class='field' style='@TextBox(0.00,0.66,7.74,0.55);font-family:"Arial";font-size:9pt;'>@{try{WriteLiteral(Out(RTrim(Ise.Tanav)+" "+RTrim(Ise.Piirkond)+" "+RTrim(Ise.Postiindek)));} catch (Exception ex) {LogiVormiViga("Out(RTrim(Ise.Tanav)+\" \"+RTrim(Ise.Piirkond)+\" \"+RTrim(Ise.Postiindek))",ex);} }</div>

</div>
<div class='row' style='min-height:0.71cm'>
<div class='field' style='left:0.66cm;font-family:"Arial";font-size:16pt;font-weight:bold;'>@Raw(IR("TULEMIARUANNE KUUDE KAUPA"))</div>

</div>
<div class='row' style='min-height:0.39cm'>
<div class='field' style='@TextBox(0.00,0.66,4.00,0.42);font-family:"Arial";font-size:9pt;font-weight:bold;'>@{try{WriteLiteral(Out(Format(Ko.Akuupaev,"-",Ko.Lkuupaev, "d")));} catch (Exception ex) {LogiVormiViga("Out(Format(Ko.Akuupaev,\"-\",Ko.Lkuupaev, \"d\"))",ex);} }</div>

...
</body>
</html>

整个模板在http://wikisend.com/download/177922/stackoverflow.TXT

结果:

.NET:

异常详情仅包含

{<Internal Error evaluating expression>}

单声道:

System.InvalidProgramException]: Method CompiledRazorTemplates.Dynamic.dbcfcaeeb:Execute () is too complex.
  at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run (RazorEngine.Templating.ExecuteContext context) <0x42194120 + 0x001b9> in <filename unknown>:0 
  at RazorEngine.Templating.TemplateService.Run (ITemplate template, RazorEngine.Templating.DynamicViewBag viewBag) <0x42193d10 + 0x0005b> in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) RazorEngine.Templating.TemplateService:Run (RazorEngine.Templating.ITemplate,RazorEngine.Templating.DynamicViewBag)
  at RazorEngine.Templating.TemplateService.Parse (System.String razorTemplate, System.Object model, RazorEngine.Templating.DynamicViewBag viewBag, System.String cacheName) <0x4218ac70 + 0x00077> in <filename unknown>:0 
  at RazorEngine.Razor.Parse[T] (System.String razorTemplate, RazorEngine.T model, System.String cacheName) <0x4218ab00 + 0x0003f> in <filename unknown>:0 

【问题讨论】:

  • 递归方法调用是 Stackoverflow 异常的原因之一。寻找那些。
  • 你能显示实际代码而不是代码的屏幕截图吗.. 导致这种情况的原因可能有很多,但如果没有看到完整的代码就很难判断跨度>
  • 抱歉,我不会从一些粗略的下载网站下载文件来回答不清楚的问题。
  • 你有一张大图。我们知道发生故障时 Visual Studio 的样子。堆栈跟踪和 Execute() 方法就足够了。有东西在呼唤自己。
  • "如果从模板中删除 ... 数量的
    ,它可以正常执行" ...因此将
    一个接一个地添加,直到您看到发生了什么.并考虑不要将 C# 放在 Razor 模板的中间。

标签: c# .net asp.net-mvc razor razorengine


【解决方案1】:

这是我一段时间以来见过的最丑陋的代码。您应该重构它以使用数组或将计算移至控制器。可能是 Mono 错误是正确的,页面 太复杂了。

dynamic _calculated21=Round(r.Total/Vjag*Iif(Core.Left(r.BilskeemKontoklass,1)=="K",-1,1),Vymardada);
_calculated21=SetDefault(_calculated21);

// about 200 similar lines snipped
dynamic _calculated229=Round(Vs52gr/Vjag*Iif(Core.Left(r.BilskeemKontoklass,1)=="K",-1,1),Vymardada);
_calculated229=SetDefault(_calculated229);

稍后:

_calculated21=SetDefault(_calculated217);
// about 200 identical lines removed
_calculated229=SetDefault(_calculated229);

【讨论】:

  • 此代码是在运行时根据用户使用报表设计器创建的报表动态生成的。控制器已经包含所有报告的通用代码。每个报告的模板计算都不同。如何将此代码移动到控制器?控制器cs文件是否也应该在运行时创建和编译?使用数组可能只会改变_calculated228 ot _calculated[228] 为什么这样更好?
  • 如何重构代码以使用数组? C# 在声明时要求固定数组大小。数组大小不知道模板生成是否开始。在模板生成过程中,如果需要新变量,其名称是使用"_calculated"+((i++).ToString()) 动态创建的。只能通过在模板启动中声明dynamic _calculated[10000] 来限制最大变量数。使用硬编码数组大小代替变量是否合理?
  • 你能改变代码生成器吗? C# 数组是堆分配的。变量是堆栈分配的。这可能会对代码生成器产生影响,它可能会限制它可以跟踪的变量数量。
  • 代码由 .NET 标准 Razor 视图引擎从 Razor cshtml 视图生成。不知道任何其他可以从类似模板生成 html 的引擎。生成 cshtml 模板的代码可以更改。可以用Dictionary&lt;int,dynamic&gt; 替换_calculated* 变量。这可能会降低报告呈现速度,因此不确定这是否合理。开发计算机有 4 GB 的 RAM + 交换文件,模板中只有 ~250 个变量。这么少的变量怎么会导致栈溢出?
  • 整个页面基本上是一个1000+行的巨大方法。我会尝试简化。轻松获胜是计算一次Iif(Core.Left(r.BilskeemKontoklass,1)=="K",-1,1)。否则考虑将代码块移动到@helper 方法或对象中。您需要dynamic 还是可以使用doubledecimal?如果您的代码生成器创建了一个包含所有这些变量的页面引用的类,而不是将它们直接转储到可能有帮助的页面上,那么可能需要做很多工作。
【解决方案2】:

您的代码@do { } while (!endOfData); 中有这样的循环确保endOfData 在某些时候变为true

【讨论】:

  • 如果删除了很多 div 和变量,报表运行正常,数据相同。日期是使用 npgsqlreader 从数据库中读取的,并且数据不是无限的。即使对于大量行堆栈溢出异常也不应该发生,也不存在递归。
【解决方案3】:

这里已经询问了如何调试 StackOverflow 异常:

基本上, 转到 Debug -> exceptions 并选中 Common Language Runtime Exceptions 处的 thrown 复选框。现在,当您导致 stackoverflow 异常时,调试器将停止。发生这种情况时,忽略异常的堆栈跟踪并转到 Visual Studio's Call Stack window 并查看那里的调用堆栈。

这将指示哪个方法正在生成无限递归。

【讨论】:

  • 我选中了调试 Windows 异常设置常见语言运行时异常中的所有复选框。发生CultureNotFound 等异常等的附加断点。对于这些异常,我从断点对话框中删除了 Break of exception of this type is thrown 复选框。 StackOverFlowException 仍然发生在问题所示的相同位置。异常细节仍然只包含在线`System.StackOverflowException {}` 如何获取其他堆栈跟踪?
猜你喜欢
  • 2011-06-11
  • 1970-01-01
  • 2010-09-11
  • 2011-11-19
  • 1970-01-01
  • 2011-04-03
  • 2019-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多