惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Help Net Security
Help Net Security
G
Google Developers Blog
雷峰网
雷峰网
WordPress大学
WordPress大学
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Engineering at Meta
Engineering at Meta
Security Latest
Security Latest
T
Threat Research - Cisco Blogs
AWS News Blog
AWS News Blog
F
Full Disclosure
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Exploit Database - CXSecurity.com
J
Java Code Geeks
U
Unit 42
C
Cyber Attacks, Cyber Crime and Cyber Security
V
V2EX
C
Cisco Blogs
博客园 - 司徒正美
Project Zero
Project Zero
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
Scott Helme
Scott Helme
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
S
Securelist
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
T
Threatpost
Recorded Future
Recorded Future
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
The Register - Security
The Register - Security
S
Security Archives - TechRepublic
博客园 - Franky
N
News | PayPal Newsroom
Simon Willison's Weblog
Simon Willison's Weblog
S
SegmentFault 最新的问题
W
WeLiveSecurity
A
Arctic Wolf
B
Blog

博客园 - 马啸西风

SQL Server 2008之XML数据存储 SQL Server 2008之托管代码 SQL Server 2008之触发器 SQL Server 2008之约束 SQL Server 2008之用户自定义函数 SQL Server 2008之错误处理 SQL Server 2008之创建高并发应用程序 SQL Server 2008之合并数据和表传递 SQL Server 2008之存储过程的设计和实现 SQL Server 2008之通过非聚集索引提高性能 SQL Server 2008之读取查询计划 SQL Server 2008之表结构实现 SQL Server 2008之索引设计 SQL Server 2008之视图的设计和实现 SQL Server 2008之表的设计和实现 SQL Server 2008之数据类型 启用Application library caching时,将多个不同步的程序集打包到一个ZIP包中的问题 DataGridView中下拉列表框的实现 C#之集合
垃圾收集导致的概率性发生的bug
马啸西风 · 2012-09-28 · via 博客园 - 马啸西风

今天开发过程中遇到一个概率性发生的bug,时而出现时而消失,而且在测试工程中无法重现,即使在实际的开发工程中也无法稳定重现。

首先说一下bug的背景:开发界面时需要一个带有提示文本的TextBox,即在TextBoxText属性为空时,显示提示文本,比如经常见到的登录界面的用户名文本框,在没有输入任何文本时提示用户“请输入用户名...”这样的提示文本,姑且将其这个文本框命名为TipTextBox,该类从TextBox继承,TipTextBox逻辑比较简单,就是重写TextBoxTemplate,在TextBoxTemplate中加入了一个TextBlock用来显示提示文本,这个TextBlockTipTextBoxText属性不为空的情况下会被隐藏掉,这就需要监听TipTextBoxText属性,一旦该属性发生变化,就判断Text属性是否为空,如果不为空,就将TextBlock隐藏;在Silverlight中不直接支持对依赖属性的监听机制,因此就写了一个帮助类,姑且将其命名为PropertyChangeListener,这个类的原理也非常简单,首先这个类从DependencyObject继承,定义名为Value的依赖属性,将这个属性和你需要监听的控件的某一个依赖属性进行绑定,当要监听的控件的依赖属性发生变化时,我们的Value属性就会随之变化,Value属性的PropertyChangeCallBack这个回调就会被执行,由此也就监听到了要监听的那个控件的依赖属性的变化。

但是在运行工程以后,发现当TipTextBoxText属性变化以后,原本期望的Value属性的PropertyChangeCallBack有时竟然得不到调用,但是无法在测试工程中重现这个bug,也无法在实际开发工程中稳定的重现这个bug。反复检查代码,发现代码的逻辑没有问题;经过排查,发现极有可能是PropertyChangeListener创建的对象被垃圾回收导致的,因为PropertyChangeListener是在TipTextBox的构造函数中定义的局部变量,用来监听控件的依赖属性的变化;为了验证这个想法,在PropertyChangeListenerFinalize方法中打印调试信息(在Silverlight中是使用Debug.WriteLine方法),这样每次都观察PropertyChangeListener这个类如果执行了垃圾回收的话,bug是否会出现;运行以后发现,只要在VSOutput窗口看到了打印的调试信息,bug都会出现,而看不到打印的调试信息的话,bug就不会出现,在这里基本就可以断定是PropertyChangeListener被定义为局部变量,被垃圾回收以后这个类的Value属性的PropertyChangeCallBack不会被调用所引起的;为了进一步验证猜想,下一步就是稳定的重现这个bug,为了保证这个bug每次都会出现,就需要强制执行垃圾收集,具体做法如下,在每次TipTextBoxLoad事件中强制执行垃圾收集,之所以在这个点强制执行垃圾收集是因为PropertyChangeListener是在TipTextBox的构造函数中定义的,到TipTextBox开始Load时,PropertyChangeListener已经没有其他对象进行引用,从而保证这个类创建的对象可以被垃圾回收,再次运行证明了我们的猜想,现在可以稳定的重现这个bug,每次刷新界面以后,这个bug也都会出现,到这里就可以断定是bugPropertyChangeListener创建的对象被垃圾回收导致的;像这样的bug在测试工程极难重现,因为测试工程中创建的对象比较少,执行垃圾收集的次数非常少,或者在测试那么短时间内根本就不会执行垃圾收集,导致无法重现bug,而在实际的项目工程下,这个bug也是时而出现,时而消失,无法找到bug出现的稳定的规律,因为垃圾收集的执行时机是不确定的;发现这个bug以后,解决办法也非常简单,将PropertyChangeListener定义为TipTextBox的成员变量,这样在TipTextBox的生存期内PropertyChangeListener这个类创建的对象都不会被垃圾收集