vasprintf 会将空间分配到栈上吗?

目录 Linux, 编程

由于提交过几次 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).

那么是不是分配失败导致了错误的发生呢?但是如果分配失败,为什么子函数返回前的指针的确指向一段在栈上的字符串呢?

长按识别二维码关注《边际效应》
长按识别二维码关注《边际效应》

11 条评论

  • Iron_Feet
    2009-05-24

    记得Libfetion刚刚发布的时候,源代码是公开的~
    但是后来DDD又不再公开。
    还引起了我诸多猜测-_-!

  • Solrex Yang
    2009-05-24

    @Iron_Feet
    唉,他要是给我源代码,我还可以耐心地好好跟一跟看看哪里出了问题。
    现在没有源代码,跟汇编太累了,尤其是这种比较大的库。

  • yef
    2009-05-24

    我曾经遇到过一个问题,就是如果用同样的va_list参数调用vsprintf函数,x86_64会core dump, 而i386不会。原因是va_list的实现方式,i386是传堆栈指针,是值方式,调用后值不变,而64位的时候是传的一个结构指针,调用后值会变,再用这个结构调用的时候,会栈越界。解决方法是用va_copy拷贝一份。也许你遇到的也是这个问题。

  • Iron_Feet
    2009-05-24

    @Solrex Yang
    既然让你加入了维护团队,还不给你源代码~个人感觉有点不厚道!

  • Solrex Yang
    2009-05-24

    @Iron_Feet
    其实不对,因为那个是 GUI 界面的项目,不是核心通信库的项目,那个库只有 DDD 一个人在维护。

  • Iron_Feet
    2009-05-24

    @Solrex Yang
    哦~我看的时候粗心了,忽略了GUI。向DDD道歉一下,哇哈哈!

  • Solrex Yang
    2009-05-24

    @Iron_Feet
    哈哈,人家不一定看到呢。
    (哈哈,我好像测试出来了在回复中添加邮件地址)

  • Solrex Yang
    2009-05-25

    @yef
    谢谢您,我们将查看该 BUG 是否由这个原因引起的。

  • sunliguo
    2009-05-26

    你好,你的代码部分是用的哪个插件?

  • Solrex Yang
    2009-05-26

    @sunliguo
    我不是用的插件
    我是用代码发芽网渲染出来HTML之后
    再用 sed 脚本稍微处理一下得到的 HTML,去掉些冗余的标签

  • sswv
    2009-05-26

    “DDD”和“调试”两个词出现在一起,还真容易误会。

发表评论

电子邮件地址不会被公开。 必填项已用*标注