由于提交过几次 Linux Fetion 的 bug 和 patch,Linux Fetion 的开发者邀请我加入了 Linux Fetion GUI 的维护者团队中。
昨天晚上和今天下午,我和邓东东(DDD)一直在调试一个 Linux Fetion 在 64 位电脑上的段错误 BUG。这是一个非常奇怪的 BUG,其表现为在 64 位电脑上(Ubuntu 9.04)运行 Linux Fetion 在登录成功后会经常出现 Segmentation Fault。DDD 确定该 BUG 存在于 Libfetion 库中,并且和读取联系人信息的函数有关。Libfetion 论坛上一直有人抱怨类似问题,但是在 DDD 的 64 位虚拟机上却无法重现此 BUG(他的 libc 是 2.7 版本的)。
由于 DDD 仍然不愿意公开 libfetion 库的源代码,我只好等每次他修改库文件之后发给我再调试。经过了好几个小时的努力,今天下午我发现,该 BUG 的主要成因非常有可能是:子函数中本应被动态分配到堆(heap)上的空间被分配(或误写)到了栈(stack)上,子函数返回调用者之后指向子函数栈内容的指针非法。
由于该动态分配的空间是使用 vasprintf 自动分配的,从 DDD 给我的部分代码来看指针传递出问题的可能性不大。那么我想,是不是 vasprintf 函数并不能保证动态分配的空间在 heap 上呢?希望对此有了解的朋友指点一下,谢谢!
$ uname -a
Linux Slytherin 2.6.28-12-generic #43-Ubuntu SMP Fri May 1 19:31:32 UTC 2009 x86_64 GNU/Linux
$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
$ ll /lib/libc.so.6
lrwxrwxrwx 1 root root 11 2009-04-13 10:26 /lib/libc.so.6 -> libc-2.9.so
PS:我在写这篇博文过程中搜索了一下 Wikipedia,发现这样一段话:
int asprintf(char **ret, const char *format, ...)
asprintf automatically allocates enough memory to hold the final string. It sets *ret to a pointer to the resulting string, or to an undefined value if an error occurred (GLibc is notable in being the only implementation that doesn't always set *ret to NULL on error).
那么是不是分配失败导致了错误的发生呢?但是如果分配失败,为什么子函数返回前的指针的确指向一段在栈上的字符串呢?
记得Libfetion刚刚发布的时候,源代码是公开的~
但是后来DDD又不再公开。
还引起了我诸多猜测-_-!
@Iron_Feet
唉,他要是给我源代码,我还可以耐心地好好跟一跟看看哪里出了问题。
现在没有源代码,跟汇编太累了,尤其是这种比较大的库。
我曾经遇到过一个问题,就是如果用同样的va_list参数调用vsprintf函数,x86_64会core dump, 而i386不会。原因是va_list的实现方式,i386是传堆栈指针,是值方式,调用后值不变,而64位的时候是传的一个结构指针,调用后值会变,再用这个结构调用的时候,会栈越界。解决方法是用va_copy拷贝一份。也许你遇到的也是这个问题。
@Solrex Yang
既然让你加入了维护团队,还不给你源代码~个人感觉有点不厚道!
@Iron_Feet
其实不对,因为那个是 GUI 界面的项目,不是核心通信库的项目,那个库只有 DDD 一个人在维护。
@Solrex Yang
哦~我看的时候粗心了,忽略了GUI。向DDD道歉一下,哇哈哈!
@Iron_Feet
哈哈,人家不一定看到呢。
(哈哈,我好像测试出来了在回复中添加邮件地址)
@yef
谢谢您,我们将查看该 BUG 是否由这个原因引起的。
你好,你的代码部分是用的哪个插件?
@sunliguo
我不是用的插件
我是用代码发芽网渲染出来HTML之后
再用 sed 脚本稍微处理一下得到的 HTML,去掉些冗余的标签
“DDD”和“调试”两个词出现在一起,还真容易误会。