除虫随记

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

除虫随记

作者:Abbey

源代码下载:IPPortAbstractor.rar(8KB)

摘要 本文讲述了本人在编写一个IP:Port提取器过程中发现 Bug 并最终排除它们的过程,并解释了原理。

关键字 VC# 正则表达式 调试

我最近在看正则表达式,加之本人又是一个 CSer,于是想着利用正则表达式从文件中提取 IP:Port

这样的服务器地址,于是便有了昨天写的这个项目(不要被它的项目名称迷惑,我本来要做个关机程序 Shutdown 的,后来才改做这个

IPPortAbstractor 的)。先看看它的界面吧。

接着我完成了最初的代码,在调试过程中发现了以下几个Bug:

1、ProcessMatch() 成员中:

Bug-1:下面这样并不会引发编译错误,但是 StringBuilder 数组的数据元素需要另行 new

,因此在运行时会触发异常“源数组中至少有一个元素无法被向下转换到目标数组类型。”我想我是把 string 与 StringBuilder

看得太简单了。

textlineList.CopyTo(strArray);

正确的做法是利用循环,如下:

for (int i = 0; i< textlineList.Count; ++i)

strArray[i] = new StringBuilder((string) textlineList[i]);

Bug-2:这样也不会引发编译错误,但会触发异常“指定的转换无效。”我看上面的转换都成功了,这里为什么就不行呢?不得其解,还请各位解释一下

matches = m_regexIPPort.Matches((string)textlineList[i]);

正确的做法是利用 object.ToString() 函数,如下:

matches = m_regexIPPort.Matches(textlineList[i].ToString());

2、buttonDelete_Click() 成员中

Bug-3:在这里,我想把用户在 Listbox 中的选中行删除,最先用的是这样的 for 循环,结果会发生无法一次性将多个选中行删除的现象

for (int i = 0; i

正确的做法如下,这也是我想到的最简单的办法了。 Bug 的产生原因在于 SelectedIndices.Count 在 Remove

操作后会发生变化,从而导致 i 的值发生变化,因此不能使用 for 循环。 while ((i = listboxResult.SelectedIndices.Count) 0)

{

// 切记:下面两条语句顺序不能颠倒

// listboxResult.Items.Remove 删除元素后将导致 m_IPPortList.Remove

// 无法定位,也会触发异常“索引超出了数组界限。”

m_IPPortList.Remove(listboxResult.SelectedItems[i-1].ToString());

listboxResult.Items.Remove(listboxResult.SelectedItems[i-1]);

}

3、保存搜索结果时一系列的 Bug

这里连续的 Bug

是项目中我最头疼的。本想在点击“退出”后弹出对话框,提示用户保存搜索结果。选择“是”进行保存,选择“否”直接退出,选择“取消”返回程序。最早

buttonExit_Click() 主要内容是这样的:

if (!IsSaved)

{

result = MessageBox.Show("搜索结果还没有保存,是否进行保存?", "保存搜索结果",

MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);

switch (result)

{

case DialogResult.Yes: //要保存

buttonSaveResult_Click(sender, e);

Close();

break;

case DialogResult.No: //不保存

Close();

break;

case DialogResult.Cancel: //返回程序,暂不退出

break;

default:

break;

}

}

结果当你点击窗口右上角的关闭按钮时没有提示,直接就退出了。于是我为 Form 生成了 Closing 事件的处理函数:

private void IPPortForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

buttonExit_Click(sender, e);

}

这下退出时提示倒是有了,但是点击“取消”之后程序也退出了,而没有返回程序。于是把 buttonExit_Click() 的内容删除其中的 Close() 调用后放在 IPPortForm_Closing() 中,而在 buttonExit_Click() 中则调用 Close() 成员。

之后发生的事就更好玩儿了:在保存结果时如果点击保存文件对话框的“取消”按钮,程序直接退出!点击保存提示对话框的“取消”程序也直接退出。这下真的头疼了!寻寻觅觅,终于让我发现 System.ComponentModel.CancelEventArgs 变量 e 中一个属性 Cancel 可用,设置其为 true 将导致该事件被取消,于是我把 case DialogResult.Cancel 分支改成这样:

e.Cancel = true;

break;

这下解决了点击保存提示对话框的“取消”程序退出的问题,但还是没有解决第一个问题:在点击保存提示对话框的“是”之后,再点击保存文件对话框的“取消”,程序还是直接退出了!想到这里,应该是保存对话框的返回值没有相应的判断,于是给 buttonSaveResult_Click() 添加了一个 else 分支:

else ((CancelEventArgs)e).Cancel = true;

问题得到解决了,但又发现了另一个 Bug :点击“保存结果”按钮时在弹出的保存文件对话框中点击“取消”时,程序在上面这条语句处触发异常“指定的转换无效。”另一方面,如果是点击“退出”按钮来弹出这个保存文件对话框则不会触发这样的异常,想来想去,只有在程序关闭事件中设置一个标志 IsClosing (初始化为 false )了,于是 buttonSaveResult_Click() 的 else 分支改成了这样:

else ((CancelEventArgs)e).Cancel = true;

IPPortForm_Closing()的 case DialogResult.Yes 分支代码改成了这样:

else

{

if (IsClosing)

((CancelEventArgs)e).Cancel = true;

}

IPPortForm_Closing()的case DialogResult.Yes分支代码改成了这样:

IsClosing = true;

buttonSaveResult_Click(sender, e);

break;

终于,我的这个 VC# 工程算是完成了。当然我没有使用 try-catch 语句块对可能的空间不足等异常进行处理。不过程序的功能上应该没有 Bug 了吧。希望大家也帮我找找。先打 CS 去了,菜鸟我的 ID: TANK---Bug 。如果遇到我千万别打我,请让我打死你吧!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航