GC竞争问题

在阅读Lua GC源码中,我们就提到过一个细节,所有带有__gc函数的对象,在第一轮GC循环中只会执行__gc函数,直到第二轮GC才真正清除。 一直没有找到必须这样做的场景,直到最近我发生了一例GC竞争的bug之后,才恍然大悟。回过头想想,其实在我之前翻译Barry Hayes大神的一篇论文里也早都提到过,只不过当时例子是释放OS资源,而场景也太过抽象,才没有引起我的注意。下面来看一个MWE。 我已经尽可能的精简代码,然而还是需要170+LOC。 在这个例子里,实现了一个链表管理,所有的link……

又一个类型提升引起的Bug

在好几年前我已经中招过一次了, 没想到最近一不留神又中招一次。不过这次的花样和上次又不太一样。 Bug的起因是,我需要一个函数,根据指定速度(可能不是整数)和距离来获取到达目的点的时间,于是就有了下面这样一段代码。 [c] //#define TIME time(NULL) #define TIME 1526796356 time_t foo(int distance, float speed) { return TIME + distance / speed; } int main() { printf("%ld\n", foo(30, 3.0f)); } [/c] 咋一看这代码几乎没毛病,严格遵循……

std::vector的错误使用

上周五服务器线上出现了几次crash,拿回dump文件分析后发现代码是崩在了对一个引用的成员变量赋值上。 分析了半天也没看出来代码有什么不妥,就先搁置了。 今天同事又给我看了一段奇怪的代码,某个类成员函数返回了某个成员变量的引用,但是当指针为NULL时去调这个函数依然不会崩溃。 思来想去搞不明白,反汇编之后终于发现原因所在。 c++引用本质上也是指针,只是不能为NULL而已。因此返回引用其实就是返回这个变量的内存地址。也就是说这个函数实际的操作仅仅是拿this指针加上这个……

bitfield数据类型的坑

bitfield并不具有可移植性,因此实际使用中,我都是尽量使用bitand来代替。 然而代码中之前就已经使用了bitfield的定义方式,作为后续开发我没有理由去改掉这个数据结构(除非它有问题),结果就无意间踩到了这个坑。 bitfield定义和使用大概如下: union utest { int val; struct stest { int a:3; int b:5; }; }; union utest t; t.value = 0x07; bitfield冒号后面的数字标识bitfield的位宽,bitfield前面的类型用于标……

当class遇上union

今天同事又踩到一个以前设计时留下的坑,这次是关于union和class中的。 虽然这种设计我并不认同, 但是至少我觉得设计者对于c++的成员内存布局相当了解。 由于面向对象的存在, 在代码中常常有这样一种用于存储属性的类,类A,类B, 类C,类B继承自类A,类C继承自类B。 而类A, 类B, 类C等这些类的实例都是从socket层传过来的。 作者在设计时为了代码的复用性, 采用了如下设计: union object { class A a; class B b; class C ……

又是权限问题

上周五发布了Beta版之后, 老板觉得这次加的功能挺多就试用了一下, 结果瞬间就崩了, 上去一顿猛批啊。 请他们试用了很久才发现又是因为权限问题。 在%ProgramFiles%下普通用户只有读取和执行的权限, 由于历史原因, 我们Client有一部分DLL是从其他地方copy到client.exe的当前目录下来动态加载的, 而这一版本恰好将管理员权限去掉了(因为Win7及以上版本在管理员权限不能访问网络共享路径), 两个巧合就碰撞到一起导致了这个bug的产生, 当然其实有些代码不是很规范, 不然应该……

权限问题引发的bug

大清早还在睡着, 被电话叫出来说软件出问题了T_T, 说软件不能解析某个文件. 软件挑文件这毛病还从没遇到过, 先把管理员权限, 文件路径是否存在等问题全部确认后没有发现异常. 万般无奈情况下, 荒谬的猜测代码打开文件时要求了写权限(如:fopen(file_path, “rb+”)), 而这个文件恰好被设置了只读属性, 会导致打开失败, 打开代码一看果然如此, 使用CreateFile, 但是却带有GENERIC_WRITE权限的要求. 发一下牢骚 🙂 这其实是一个典型的权限问题, 在此之前曾经碰到过, 在Win7以……

一个类型提升的bug

今天碰到一个由于类型提升的bug, 即使找到bug后, 仍花了好大功夫才找到解释, 感觉此坑比较隐蔽, 在此小记一下. 有类似下面一段代码: unsigned char a; unsigned char b; a = -1; b = 0; if (a == b - 1) printf("equal"); else printf("not equal"); 理论上当a为-1, b为0时应该打印出equal. 可事实恰恰相反, 打印出来的是not equal. C语言中有以下类型提升规则: 2. 一般常数为int型 1. 二元操作符如果两个操作数具有不同的类型, 那么将较低的类型提升为较高的类型……

多线程调DLL

最近写代码一不小心又着了多线程的道, 背景如下: 前不久写了这样一个DLL: const wchar_t *a = L"xxxx"; const wchar_t *b = L"xxxx"; int do_something_a(struct axx *param_a) { ... } int do_something_b(struct bxx *param_b) { ... } 在do_something_a与do_something_b中分别用到了字符串a, b.本来这样相安无事, 可是很多地方会用到这个DLL的代码, 但是字符串a, b并不一样, 而字符中a, b可以根据param_a, param_b中的信息来生成, 本着代码正交性的原则, 将DLL……

由于滥用void *引发的bug

我一向认为在写代码时,void *滥用是有问题的,在最近的一次代码中, 有类似这样一段代码:   [cc lang=”C”]int send(void *buff, unsigned long size); int xx_func(char *buff, unsigned long size) { unsigned send_size; ……… send(&buff, send_size); return 0; }[/cc] 暂且不论为什么作者会错写成取地址,但其原意是想发送经过处理后的buff里面的内容, 但是编译器是不会报错的,因为void *默认兼容所有类型,如果把代码改成下面这样:……