维生素C.net
Talents come from diligence, and knowledge is gained by accumulation 天才源于勤奋,知识源于积累。
难忘的1654天
博客园  首页  新随笔  新文章  联系  管理  订阅 订阅
随笔- 220  文章- 1  评论- 1648 
ASP.NET崩溃 - SiteMap里的疯狂循环(概译)

作者:tess
原文地址:ASP.NET Crash - Crazy looping in a SiteMap

本文只是一个快速的概括性翻译, 如果敢兴趣还请您看原版.

我想快速创建一个并不美观的站点地图(site map), 所以我只简单的在我override的BuildSiteMap()函数里使用一个小循环添加了几个地图节点(sitemap node)

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;
}

当我运行这个web应用程序的时候我得到的却是"堆栈溢出(Stack overflow)",然后服务器就崩溃了. 然后我借助调试器调试这段代码,我所看到的东西非常奇怪:

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

看起来i的值并没有增加,是编译器的bug还是CLR的?(暂时撇开sitemap的内部机制, 因为sitemap从设计上不允许我们这么使用,但是这个条语句你却可以随便写的)

在debug之前我们向后退几步重审一下:

  1. 堆栈溢出
  2. 一个看起来像是无尽的循环

造成堆栈溢出是因为我们已经占用了大量的内存,而它们是当初为了在栈上分配太多的指向指向局部变量或参数的指针而服务的.(we have exceeded the amount of memory reserved for the stack by allocating too many function pointers, pointers to local vars and parameters on the stack.)但是往往我们都是因为死循环(never-ending recursion)而造成的, 换言之, funcitonA()调用了functionB(),而functionB()里又调用了functionA().

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

}
 

所以此时我们的调用栈(callstack)看起来应该是这样的:

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

好,那我们现在想象一下如果你现在有这样的函数:

当你第一次在断点位置上停止的时候i的值应该是0,调用栈看起来应该是

MyRecursiveFunction()
...

现在我们用另一种方式执行进入函数内部(其实还是它本身)

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++){
                     
                  }
               }
            }
         }
      }
   }
}

所以调用栈应该是这样的:

MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
 

调试:

将windbg附属到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来看一下.
(注意:!dumpstack不展示真实的堆栈,有一些函数可能是错误的,但是它能很好的让我们知道究竟怎么了)

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())
...

Ok,看起来问题出在ChildNodes属性上了, 它调用GetChildNodes()函数,而GetChildNodes()又再次调用我们的BuildSiteMap函数, 该函数调用了ChildNodes属性, 所以这样造成一个死循环.

结论:

在创建站点地图一文中你可以找到答案和解决文章开始时问题的正确处理方法.

posted on 2006-10-12 14:59 维生素C.NET 阅读(2661) 评论(2)  编辑 收藏 所属分类: ASP.NET

发表评论
  回复  引用    
2006-10-13 10:29 | juqiang [未注册用户]
good!!!

不过这个例子太简单了。
  回复  引用  查看    
2007-03-25 22:07 | JesseZhao      
哥们是烟台的
新用户注册  刷新评论列表  

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
网站首页

新闻频道

社区

小组

博问

网摘

闪存

找找看

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      

相关文章:
ASP.NET实用技巧(一)
ASP.NET跨页面传值技巧总结
ASP.NET AJAX入门系列
.NET设计模式系列文章
ASP.NET下如何浏览客户端文件夹
学校有关于ASP.NET和JSP的课程 有必要都学习吗?
建议博问中增加ASP.NET MVC分类
深入剖析ASP.NET组件设计

相关链接:

所属分类的其他文章:
为LINQ提速的i4o和增强功能的SLINQ
结构体,值类型和接口
ASP.NET崩溃 - SiteMap里的疯狂循环(概译)
Inbox.com使用的asp.net和ajax技术
NOCOUNT如何影响ADO.NET(SET NOCOUNT ON的性能问题)
30hrs Wire [1]
利用数学方法来大大降低一个逻辑判断实现的难度的例子
在配置使用Membership或其他的Providers的ASP.NET2.0时一定要设置applicationName属性
在Atlas中实现检测postback progress的状态的方法
【翻译】Atlas Documents : UpdatePanel Class

最新IT新闻:
51.COM技术副总裁邵辉跳槽百度
Mono 2.0终于到来
百度任命李一男担任首席技术官
Google Knol 开始尝试有声版
12日电脑与人进行世纪对话 可思考机器或诞生
 



公告

view my mvp profile 看看有多少人来访问我的Blog了!
hotmail

<2006年10月>
日一二三四五六
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

与我联系

  • 发短消息

搜索

 

常用链接

  • 我的随笔
  • 我的空间
  • 我的短信
  • 我的评论
  • 更多链接
  • 我的参与
  • 我的新闻
  • 最新评论
  • 我的标签

留言簿(168)

  • 给我留言
  • 查看留言

我参与的团队

  • 北京.NET俱乐部(0/1544)
  • 烟台.NET俱乐部(0/47)
  • ASP.NET AJAX (Atlas)学习(0/1352)
  • MVP(微软最有价值专家)团队(0/634)
  • 博客园培训团队(0/111)
  • Silverlight学习与研究(0/285)
  • CLR基础研究团队(0/405)

随笔分类(148)

  • ASP.NET(26)
  • Code Warehouse(20)
  • IronRuby,DLR(2)
  • LINQ(3)
  • Reading(3)
  • Training@cnblogs(23)
  • Ubuntu(4)
  • Windows Live(6)
  • Windows Mobile(7)
  • XHTML & Web Standard(54)

随笔档案(220)

  • 2008年3月 (2)
  • 2008年1月 (3)
  • 2007年12月 (3)
  • 2007年9月 (1)
  • 2007年8月 (2)
  • 2007年7月 (3)
  • 2007年6月 (3)
  • 2007年3月 (4)
  • 2007年2月 (3)
  • 2007年1月 (1)
  • 2006年12月 (1)
  • 2006年11月 (8)
  • 2006年10月 (6)
  • 2006年9月 (11)
  • 2006年8月 (5)
  • 2006年7月 (4)
  • 2006年6月 (1)
  • 2006年5月 (10)
  • 2006年4月 (8)
  • 2006年2月 (2)
  • 2006年1月 (1)
  • 2005年12月 (11)
  • 2005年11月 (13)
  • 2005年10月 (3)
  • 2005年9月 (1)
  • 2005年8月 (4)
  • 2005年7月 (3)
  • 2005年6月 (4)
  • 2005年4月 (5)
  • 2005年3月 (10)
  • 2005年2月 (7)
  • 2005年1月 (28)
  • 2004年12月 (15)
  • 2004年11月 (10)
  • 2004年10月 (5)
  • 2004年9月 (1)
  • 2004年6月 (13)
  • 2004年5月 (5)

文章档案(1)

  • 2005年5月 (1)

相册

  • ASPNET2tutorial
  • BlogUsing
  • My love and my friends
  • newGallery
  • 下一代网络图片

.net网站收藏

  • ASP.NET2.0 Tutorial
  • CodeBetter.com
  • F#
  • IIS.net
  • MS NewsGroup
  • NewsGroups
  • OnlyVC.org
  • VWD2005GuidedTour
  • ZDNet China软件技术专区

OSS 2007

  • Charsh
  • Kaneboy
  • Official Team Blog

Python

  • BeginnersGuide

好友的BLOG

  • DemoFox@JoyCode
  • DflyingChen
  • dudu
  • EricLee
  • hbifts
  • idior
  • Jesee Qing
  • Lion
  • Rickie
  • Samuel
  • Steph`s Website
  • 翱翔.Net
  • 陈敬熙
  • 发条木偶
  • 葛涵涛
  • 古道风
  • 寒枫天伤
  • 老猫の理想
  • 刘老师
  • 刘彦博
  • 吕震宇
  • 木野狐
  • 佘广
  • 王sir
  • 小涛
  • 小新
  • 肖老师
  • 旋哥

积分与排名

  • 积分 - 397796
  • 排名 - 56

最新评论

  • 1. re: 加入[ 下一代网络web技术(Next Generation Web Application)团队Blog ]
  • 加! 加! 加!
  • --… 黒液...
  • 2. re: 加入[ 下一代网络web技术(Next Generation Web Application)团队Blog ]
  • 在下也是开发java Web的 希望加入!!
  • --… 黒液...
  • 3. re: .NET Beginner Training Step by Step开始启动
  • 我的ID: nocry

    申请参加 谢谢
  • --夕阳
  • 4. re: .NET Beginner Training Step by Step开始启动
  • 早班加入
  • --石牌村夫
  • 5. re: .NET Beginner Training Step by Step开始启动
  • 申请加入!谢谢!
  • --童话@混子

阅读排行榜

  • 1. 英文名字及含义(25339)
  • 2. SQL Server 2005 Remote Access(15130)
  • 3. Visual Studio 2005 Team Edition和SQL Server 2005的下载(14358)
  • 4. Windows Installer 3.1(11513)
  • 5. Visual Studio 2005 Professional Released(10992)

评论排行榜

  • 1. .NET Beginner Training Step by Step开始启动(320)
  • 2. Windows Live Messenger 8.0 Beta 的邀请(100)
  • 3. 加入[ 下一代网络web技术(Next Generation Web Application)团队Blog ](90)
  • 4. 博客园新手.net技术培训活动(55)
  • 5. 为什么在vista上做开发?(54)
Copyright ©2008 维生素C.NET