程序调试有感
程序调试有感
Risun
最近赶上回家和软件发布的冲突之中,最要命的是程序运行的过程中出现bug,最致命的内存访问异常错误,一旦出现立即中止,这,对于一个需要7*24运行的服务器来说是不可忍受的。
于是乎,和时间赛跑和冗长的代码比耐心,开始了痛苦而兴奋的程序调试历程……
由于是内存错误,开始时总是会随机的出现在一些地方,好像没有什么固定地点,但出的次数多了,终于发现了一个最多出现的部分,于是手工察看此部分代码,怀疑copy constructor有问题,单步跟踪后,竟然发现,一直以为很有用的copy constructor竟然根本从来就没有调用到。晕,真是奇怪前一个版本为什么在实际项目中用了这么久!
测试copy constructor的用法,(参见<关于copy constructor>一文)修改了整个类体系的copy constructor。意料之中的,引入了或者说暴露了一大堆新的bug。由于以前很多代码根本就没有执行到。再修改,测试,这部分的问题似乎得到解决。
怀着激动兴奋得心情再次运行修改后的服务器和测试程序,呵呵呵,没错了,要是不出错多好,可以回家了~~
卡擦~~,一个悬着的心终于掉到石头上,摔得粉碎,还是有内存访问异常。
Release下的调试堆栈看的人一头雾水,debug时它偏偏不出错,只好一次次的让他重复出现“随机的错误”。终于又抓住一个把柄,线程的问题,主线程创建了子线程,子线程delete之后,主线程还在访问字线程中的变量(出错代码见附录),修改之,运行之。
根据前面的出错记录,感觉还有错误,明显不是由刚刚修改的错误导致。
果然,程序还是出现错误了。
这时差不多整个服务器的代码都重看了一遍,在这种头晕脑胀两眼发花的状态下,能看出代码的错误?
再让程序重复出错,终于发现似乎有一套代码是祸源,就要抓住你,我看,我查,实在看不出问题,但有一种预感这里有问题,让别人帮我看,还是没有结果,心中凄凄然,吃饭没有精神,骑车无精打采,突然间似乎想起什么?对,呵呵,太兴奋了。
立马赶到公司,修改了此处的代码,ok。
有一种感觉,终于解脱了。
再测试,再也没有出现问题,不能肯定没有了错误,只是心中有了一种踏实的感觉。
没有经历过程序调试,无法体会其中的失望、茫然、烦躁、希望、激动和兴奋。经过这段程序调试的历程,审视了以前的代码,前所未有的感受到很多以前写代码时未曾注意的地方。
无论写一个函数一个类或者一个库,一定要自我认为她是完美的,不会对外界造成破坏也不会被外界破坏。写完代码自己就要检查一遍,至少要自己放心,千万不可有侥幸心理,那必将埋下一个让你付出惨重代价的地雷。
在写程序时特别要注意 指针、copy constructor、多线程访问的部分
刚刚给老板打了一个电话,他听了也很开心,因而允许了我的放假半个月的请求,回家了,88。
附录:出错代码(删节)
1 线程相关
void Thread::start()
{
DWORD wt_id;
thdl = ::CreateThread(NULL, 0, ThreadEntrance, this,0,(LPDWORD)&m_id);
if(!thdl)
{
assert(0);
return;
}
// to wait for the child thread to run
start_lock.wait();
}
被主线程调用创建新的线程
int Thread::_run()
{
int ret;
start_lock.signal();
ret = run();
delete this;
return ret;
}
子线程的执行体,主线程创建子线程后等待字线程运行起来,但有时主线程还没有到start_lock.wait();子线程已经执行完,并且delete this了
2 指针、 copy constructor相关
class ATB_FieldItem
{
public:
virtual ~ATB_FieldItem() {}
};
class FieldItemImpl : public ATB_FieldItem
{
public:
FieldItemImpl();
virtual ~FieldItemImpl();
FieldItemImpl( const ATB_FieldItem & item );
private:
union {
long vl;
double vd;
wchar_t * vs;
int_64 vi64;
byte_8 * vb;
} m_val;
};
以FieldItemImpl为模版构造FieldItemImpl对象时根本不会调用类中定义的copy constructor而是使用默认的copy constructor,会导致什么?m_val.vs不能被正确设定
修改:copy constructor 该为:
FieldItemImpl( const FieldItemImpl & item );
LockTarget::LockTarget(const LockTarget &model)
{
//init();
*this = model;
}
这里有错误吗?有!一般的在 A = B时A是一个已经初始化好的对象,因此在
LockTarget & LockTarget::operator = (const LockTarget &right)
{
if ( this == &right )
return *this;
clear();
//… set data
return *this;
}
中首先清理A,如果在copy constructor直接调用*this = model;这时this还没有被初始化,有些成员变量可能是无效或者可能引起后面的clear()的错误,因此如果在copy constructor中用 = 来实现,则首先应该初始化对象, 如代码中的init();
posted on 2004-07-31 20:39 哲学 艺术 程序 人生 阅读(483) 评论(0) 收藏 举报
浙公网安备 33010602011771号