Archive for March, 2013

我的BUG大全。

在这里记下我的程序BUG

# buff溢出后,把栈破坏了,这个线程也没崩溃,一直死循环在一小段不可知的代码里。

#调用getaddrinfo很多次以后,getaddrinfo报错:No address associated with NAME。非常地奇怪呀~~后来把同样的程序部署到比较旧的linux上,报错: Too many open files。才明白,原来fd被用光了。回头再检查相关代码,果然如此~补上close(fd)后,getaddrinfo的问题也解决了。启发是:1. 有些报错信息其实离真正的错误原因很远。2. 一个系统调用一开始正常,跑了很多次后失败,应该怀疑是不是有资源泄露。

#把uint_t类型赋值给std::string时,会崩溃在std::string里面。

#当一个预期统一的规则出现特例的时候容易出现BUG. 关联订单,关联片区,入货地址都指受YYYY-MM-DD HH:MM:SS的时间戳,但同机分析接受的时间戳却是YYYYMMDD某一天的时间戳。有一个组合需求是同时导出上述4个小需求时,由于传入的时间戳参数不一致导致了BUG.

# vector::push_back可能会重新分配vector的内存,导致指向之前元素的引用和指针失效.一个std::function持有一个std::ref指向vector中的一个元素,当这个funcction被调用的时候,vector中的这个元素已经失效了。

# 用boost::optional记录一个信息。这个信息没及时在clear函数里做清理。于是,观察到的情况时,这个信息总是被打印。但一开始,我们却怀疑是另外的函数不稳定而重新生成了该信息。

# 在写一个匹配函数时,待匹配操作数是一个字符串,我没有考虑字符串是空串的情况。

# 在比较旧的gcc 4.1.2上把shared_ptr赋给 weak_ptr时,崩溃。溃在atomic_exchange_and_add。一开始怀疑是旧版gcc对boost的智能指针支持的不够好,后来发现是因为weak_ptr此时已经失效了。原因是用handler的参数持用shared_ptr的引用做生命期管理时,传错了参数,使得这个对象已经被销毁了。

# 现象:一个依赖某布尔变量的逻辑大多数时候正常,少部分时间异常。期望这个布尔变量是false,有时候陌名其妙变成了true。

原因是此布尔变量未被初始化,大多数时候它的值是false,但有时却不是。

#. 现象rmap_item泄露.

Fix it: 单链表插入新结点时指针操作出错。应该是new->rmap_list = *item,被我写成 new->rmap_list = (*item)->rmap_list.

#. 我意图注释掉某行代码,却鬼使神差注释错了一行代码。

#. 变量名 pkt 和ptr 很像,在用memcpy函数时用错了变量导致bug. 一块内存被莫名其妙的修改了,很有可能是因为像刚才这样写这块函数的参数填错了。

#. _sessions.erase(ite++);删除了_sessions维护的一个对象.对象的析构被调用,会有一连串对象的析构因此而被调用。这些对象中的指针很可能就失效了。但是,在代码的其它地方还能拿到这个指针。野指针啊!!!今天这个例子中是session维护的ip_pkt对象都被析构了,ip_pkt中的指针也都失效了。于是,一使用野指针,崩溃了。

#. 删除数据时,总是要注意其它代码中指向这些被删除数据的引用或指针。

#. 解引用container.end()返回的迭代器会崩溃。

#. 这是个腾讯视频广告投放组的bug. 一个线程负责开,关FD。另一个线程读写FD。两个线程的竞争条件造成了BUG.

#. 写代码时偷懒复制代码,然后忘记做相应更改,视觉上很难在第一时间察觉,却在后期花费了几倍时间调试程序。

#. 写判断语句时,判断表达示如 container.empty()之前是否要取反,经常搞错。

#. htonl 写成 htons

#. std::distance 计算两个迭代器之间距离时死循环,是因为迭代器没有初始化。而我之前想,作初始化工作的函数已经调用了,实际上并没有被调用。

#. 没注意函数的返回值. 有时函数返回0时表示成功,即true的含义。所以看到一些和预期刚好相反的现象时,应该考虑是不是出现了这样的错误。

#. 又是迭代器失效。erase(ite++), continue,但是for循环里有++ite。结果迭代器被加了两次。

#. 追踪到原因是野指针。野指针的特点是在调试器里会看到乱七八糟的值,如果只看一些标志变量会让人觉得颠覆了之前建立的逻辑,于是又去跟踪逻辑有没有问题。而这次bug,逻辑本身没错,而应该去找野指针是如何产生的。这次的野指针产生是因为负数取模后得到负数,又用这个负数作为索引去拿对象,结果拿到了无效的对象。这次的经验是,即使是超级简单的一些逻辑,觉得自己一定能保定索引是用效的,但一些不经意的代码给你生产了不合法的索引,于是花费大量时间追踪。对简单的判断多下诊断喔!

# 在实现一个clone函数时,new出了新的对象,想要引用新对象的数据的时候很容易忘用新对象的引用来引用新对象的数据,于是新对象的数据并没有正常赋值,又写坏了this的数据。

# 又是指针操作越界,因为各种length计算出错。

# timer表示一个局部定时器, timer_是一个class的定时器。因为没看到下划线~~搞错了!!!

# 一个指向char 的 ite,解引用这个ite后赋给 int,因为char是有符号的,int也是有符号,所以当char是负数时int也是负数。

# 两个容器中存放了指针指向同一批对象。清理的时候,delete了A容器中的指针指向的堆空间向,给A调用了clear。但是,B容器忘记clear了。结果,B容器中的指针都变成了野指针。

 

Be the first to comment - What do you think?  Posted by zausiu - March 23, 2013 at 11:32

Categories: Tech Articles   Tags: ,