首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 认证考试-> 全国等级考试
asp.net 崩溃-sitemap中疯狂的循环_asp.net技巧
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

原文地址:http://blogs.msdn.com/tess/archive/2006/10/10/ASP.NET-Crash-_2D00_-Crazy-looping-in-a-SiteMap.aspx
发布时间:Tuesday, October 10, 2006 4:10 PM
作  者:Tess      

一天,我收到了一封有关我的博客的邮件,提出如下问题,简述如下:
 
我想快速地创建一个站点地图,因此我重写了BuildSiteMap()方法,在里面我写了一个循环,用以添加一些仿造的sitemap节点。


public override SiteMapNode BuildSiteMap(){
   for (int i = 0; i < 5; i++)
      myRoot.ChildNodes.Add(new SiteMapNode(this, i.ToString(), i.ToString(), i.ToString()));
   return myRoot;
}

运行程序,就发生堆栈溢出,服务器也崩溃了。我用调试器单步调试,发现真的很奇怪: 

1) int i = 0
2) i < 5
3) myRoot...
4) int i = 0
5) i < 5
etc.

i的值看起来从来没有增加,除非我调用到SiteMapNode(access a property, call a method),看起来这个循环是正确的。
是什么使得这个循环不确定呢?咋看可能是编译器或者是CLR的一个bug.

(当我获此问题时,我真不知道ASP.NET2.0中的站点导航,但我找到了这些文章... http://weblogs.asp.net/scottgu/archive/2005/11/20/431019.aspxhttp://aspnet.4guysfromrolla.com/articles/111605-1.aspx ,叙述得真是很不错.)

 

最初的想法


这个问题最重要的就是它始终重新开始, 这就意味着可以对此做现场调试。但我们暂不走那么远,先回头看看现在有什么...


1. 堆栈溢出


2. 一次又一次重新开始的循环


 我已经在先前的博客帖子里讨论过堆栈溢出,现在重复一下...    引起堆栈溢出的原因是, 分配了太多的函数指针,变量指针和参数,以致在堆栈里申请的内存数量不够用。到目前为止,堆栈溢出最平常的原因是无终止的递归。换句话说,function A调用了function B, function B又调用了function A...


因此,callstack看上去有点像这样....


...
functionB()
functionA()
functionB()
functionA() 


好了,一切都好极了,但那仅仅解释了堆栈溢出。那么疯狂的循环是怎么回事呢?
 
好...想象一下有这样一个函数(在-->处有有一个断点)


void MyRecursiveFunction(){
     for(int i=0; i<5; i++){
-->      MyRecursiveFunction();
     }
}


当你第一次停在断点处,i的值应该是0,callstack看起来是这样的...


MyRecursiveFunction()
...

 

现在调用MyRecrusive函数,每一次调用这个函数自己,会再一次出现 i=0(虽然我们并不真的在同一个loop里)。若调用MyRecrusive这个函数几个来回,并用实际执行的代码代替之,它将执行类似如下的代码:


for(int i=0; i<5; i++){
   for(int i2=0; i2<5; i2++){
      for(int i3=0; i3<5; i3++){
         for(int i4=0; i4<5; i4++){
            for(int i5=0; i5<5; i5++){
               for(int i6=0; i6<5; i6++){
                  for(int i7=0; i7<5; i7++){
                     ...
                  }
               }
            }
         }
      }
   }
}


... 在visual studio中查看它,看起来总是运行同样的循环,且并不改变变量i的值。暂时,你对此不会有深层次的理解,直到你真正看到堆栈调用。
假如我们看一下callstack, callstack现在看起来是这样的...

MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
...

因此最初想法的结论是,我们无疑地要看看某些递归...但在哪呢?例子中的代码

      myRoot.ChildNodes.Add(new SiteMapNode(this, i.ToString(), i.ToString(), i.ToString()));

看起来并不是那么复杂...

在这儿最可疑的是new SiteMapNode() 和myRoot.ChildNodes.Add() ,假如我们用reflector查看一下,那么这将不再那么神秘。
 

调试问题


最后:)  少一点口舌,多来一点windbg行动...


因它易重新呈现,所以我会在我的机器上重新呈现它,我只要将windbg (File / Attach to process)附到w3wp.exe上,点击g开始即可。然后会重新产生了这个问题,程序中止时提示我这是一个堆栈溢出(我们已经知道了)。
 
(7e4.ddc): Stack overflow - code c00000fd (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0fa4235c ebx=02beca74 ecx=02beca74 edx=02becb54 esi=02becb54 edi=02beca74
eip=686b5cb4 esp=02163000 ebp=02163004 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210246
System_Web_ni+0xf5cb4:686b5cb4 56 push esi

我们查看一下堆栈,使用 !clrstack命令看看是怎么中止的,但我们只能看到....


0:016> !clrstack
OS Thread Id: 0xddc (16)
ESP EIP 02163000 686b5cb4 System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode)

 ... 这对我们并没有太大的帮助。有时当我们遇到堆栈溢出时,使用!clrstack 命令就会出现一些这样的问题。因此我们还需要使用!dumpstack命令查看一下raw stack。


0:016> !dumpstack
OS Thread Id: 0xddc (16)
Current frame: (MethodDesc 0x68b03720 +0x4 System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
ChildEBP RetAddr Caller,Callee
02163004 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
0216300c 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
0216303c 686b5cdf (MethodDesc 0x68b03720 +0x2f System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
02163074 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
0216307c 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
021630ac 686b5cdf (MethodDesc 0x68b03720 +0x2f System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
021630e4 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
021630ec 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
0216311c 686b5cdf (MethodDesc 0x68b03720 +0x2f System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
02163154 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
0216315c 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
...

好了,这看起来问题出自ChildNodes属性。使用该属性时,会调用GetChildNodes 函数,这个函数会再次调用BuildSiteMap 函数,从而它又调用了ChildNodes 属性,如此一直下去,导致了堆栈溢出。


结论


 在关于BuildSitemap的文档中,你能找到如下段落:
 
BuildSiteMap 方法由 FindSiteMapNode、GetChildNodes和GetParentNode方法的默认实现调用。如果在派生类中重写 BuildSiteMap 方法,请确保它仅加载一次站点地图数据,并在后续调用中返回。
为了避免出现递归和堆栈溢出,最好避免调用该方法,像在BuildSiteMap例子里,我们可以用AddNode方法来添加子节点。
这在归档在Site Map Providers这篇文章中,该文同样值得一读。
BuildSiteMap 一般不应当调用其他的site map提供的方法或属性,因为许多方法和属性默认会实现BuildSiteMap调用。 例如,BuildSiteMap中的RootNode会引起递归,从而使之以堆栈溢出而终止。 
http://www.cnblogs.com/Ring1981/archive/2006/10/19/443280.html


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·VisualC#中MDI窗体初步-.NET教程,C#语言
·2004年全国计算机等级考试二级vb全真上机试题解析
·全国计算机等级考试一级ms office考试(样题)
·java生成JPEG 图像文件-JSP教程,Java技巧及代码
·全国计算机等级考试二级access考试大纲
·全国计算机等级考试一级b考试大纲
·大文件上传研究-ASP教程,ASP应用
·全国计算机等级考试二级c语言考试大纲
·C#字符串的使用笔记-.NET教程,C#语言
·c#实现类似于SqlServer视图设计器的可浮动窗体-.NET教程,C#语言
最新文章
·利用c#远程存取access数据库_c#应用
·dreamweaver简单描述制作网页的基本步骤_dreamweaver教程
·fireworks制作波普网点画面特效_fireworks教程
·如何提高垃圾站点gg ad广告单元点击价格_网赚技巧
·谈百度联盟和google adsense广告的均衡优化_网赚技巧
·google adsense 广告功略之三定理_网赚技巧
·为什么网站要先做小众_站长心得
·针对地方门户网站运营推广的经验分析_站长心得
·如何做网站的搜索引擎优化?_站长心得
·如何正规的快速建立赚钱的网站_google推广
相关主题
  • asp.net应用程序资源访问安全模型_asp.net技巧
  • asp.net中多彩下拉框的实现_asp.net技巧
  • asp.net中数据校验部分的封装与应用_asp.net技巧
  • asp.net网络编程中常用到的27个函数集_asp.net基础
  • asp.net2.0学习历程 菜鸟到中级程序员的飞跃_asp.net基础
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭