一个让人崩溃的编码错误
2014-05-25 17:33
162 查看
最近写了一个接受socket数据包,然后再重组上层协议包的东西。每次read到数据就将数据添加到一个链表的尾部,然后检查是否收到了一个完整的包。为了减少内存碎片,把用过的链表节点添加到另外一个链表中,这样下次可以从这个cache链表中重用节点。 在debug的时候我把cache list中的数据打印出来,代码如下:
struct seg_node { void* buf; unsigned int capacity; void* data; /* data >= buf, data is the position where available data begin with. */ unsigned int size; struct list_head list; };
struct my_pkg_reasm{ struct list_head seg_list; struct list_head cache_list; unsigned int cur_total_size;};
void check_cache(struct my_pkg_reasm* reasm){ unsigned int count = 0; struct list_head* pos; printf("----------------cache list--------------------\n");list_for_each(pos, &reasm->cache_list); { struct seg_node* node = list_entry(pos, struct seg_node, list); printf("capacity : %u, size : %u\n", node->capacity, node->size); } printf("-----------------------------------------------\n");}最开始的时候,cache list是空的。但是这个check_cache函数却输出了一个节点的数据(数据是有问题的数据)。一看那个数据是有问题的(capacity非常大),我猜测应该是其他的代码哪个地方踩内存了。检查了N遍代码,没发现问题。哥就郁闷了,麻痹哪里出问题了?由于glibc的list.h中并没有list_for_each宏(目前只有list_for_each_prev),所以我自己加了一个list_for_each,然后我又去检查了N遍list_for_each宏:
# define list_for_each(pos, head) \ for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)/* Iterate forward over the elements of the list. */# define list_for_each_prev(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev)检查了N遍,也没发现问题。那一刻,我竟然怀疑起linux系统了....... 于是,我默默地reboot了... 重启后,再去运行问题还是一样。 于是,我在cache_list的prev和next处加watchpoint,然后各种gdb调试,调试过程中并未发现内存被踩。当时真是无语了,果断不玩了,去打了局魔兽,然后吃了个冰激凌爽爽先。然后再来看看这个问题。这次仍然是GDB单步调试,只是这次更加仔细一些(平时本人比较马虎,看什么东西总是扫一眼,凭感觉),突然发现一个问题!!!!:
list_for_each(pos, &reasm->cache_list);那一刻,感觉像在路上捡到了一万块钱(捡到100块绝对不是那感觉)!!!有了这个分号,不管链表是不是空的,下面的代码都可以进去,而且正好节点前后的内存是可以访问的,所以没有发生段错误而是打印了一些奇怪的数据。 总结:怎么说呢,也不能说我是新手。这个问题怎么才能防止呢,我觉得一方面写代码时要细心,另外一方面,可以引进一个代码检查工具,像while for if之类的语句后面如果直接跟的分号,应该出一个告警。
相关文章推荐
- IOS错误异常一个未知的实例在运行,出现程序崩溃
- 水题第三记 一个小错误引起的崩溃
- 自作聪明导致的一个Java编码错误
- 绿色版SecureCRT启动崩溃,遇到一个致命的错误且必须关闭
- 一个编码引发js错误的问题
- Win7 一个让人崩溃的错误消息
- swift + 百度地图 初始化BMKMapView崩溃 不报错 无打印 (一个愚蠢的错误。。。)
- Apache的一个错误:[error] an unknown filter was not added: PHP
- [解决] DreamWeaver MX 2004 打开一个已存在的未指定编码的文件时出现乱码
- 一个不起眼的错误可能会纠缠你很久
- 一个犯了N久的错误
- 一个容易犯的错误
- 一个if 判断条件的常见错误
- 错误“操作必须使用一个可更新的查询”原因及解决办法
- C标准库函数abs的一个错误
- 一个低级错误导致的StackOverflowException异常
- 设计Property时常犯的一个错误(set)
- 一个简单的错误,一直没有仔细考虑。
- 克里1971年的反战演讲:“你怎么能够要求最后一个人为一个错误的政策去死?”
- Windows Form 和 UserControl的“未将对象引用设置到一个对象实例”错误