动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > ASP.NET技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ ASP.NET技巧 ]的信息

本月文章推荐
.通过序列化和反序列化泛型数据实.
.如何实现Asp与Asp.Net共享Session.
.在.NET框架应用程序中发送电子邮.
.Asp.Net使用POST方法最简单的实现.
.虚拟主机上asp.net运行权限不足问.
.GridViewRow可以任意位置单击引发.
.DataGrid的多行提交.
.ASP.NET超时设置.
.创建ASP.NET程序时候发生错误"HT.
.在ASP.NET 2.0中使用RDLC格式的报.
.ASP.NET中实现中文简/繁体自动转.
.借助HiddenText 确定CheckBoxLis.
.ASP.NET编程中的十大技巧.
.如何制作winform得启动画面.
.asp.net在ie里调试.
.一些常用的数据操作类.
.爬虫如何抓取到Asp.Net中-doPost.
.实现asp.net只对个别控件实时访问.
.在IIS6.0下ASP .NET 的版本冲突问.
.URL重写可删节日期模式---正则表.

ASP.NET 崩溃-SiteMap中疯狂的循环

发表日期:2006-10-20 |


原文地址: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

上一篇:ASP.NET里常用的JS 人气:4492
下一篇:两种添加数据到DropDownList控件的方法 人气:4659
浏览全部ASP.NET的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-8-21 Nucleus v3.33 多国语言版
2008-8-21 HDWiki v4.0 bulid 080821 UTF-8
2008-8-21 明科在线客服系统 v6.0
2008-8-21 KesionCMS v5.0.2 正式版 utf-8
2008-8-21 KesionEshop v5.0.2 正式版 utf-8
2008-8-21 HDWiki v4.0 bulid 080821 GBK
2008-8-21 新文互动酷站展示系统 v1.5
2008-8-21 Punbb v1.2.20 多国语言版
2008-8-21 QQ头像网 beta
2008-8-16 iLaba Player(小喇叭播放器) v2.
2008-8-16 DoubleClickFix 鼠标双击修正工具
2008-8-16 CrystalCPUID 4.15.2.451
2008-8-16 VeryCD 电驴(easyMule) 1.0.4 Bu
2008-8-16 uTorrent 1.8 Build 11813 - Sta
2008-8-16 比特精灵(BitSpirit) v3.3.2.287
2008-8-16 StayInTune音叉 v1.0 破解版
2008-8-16 iChing《周易》汉化补丁 v1.0
2008-8-16 Starmap星空图v1.0汉化破解版
  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号