我是在使用别人源码(DBT2 benchmark)的时候,编译成功然后运行就出现了这个问题。本以为像这种开源的软件应该没什么太明显的bug,但是后来细想,buffer overflow暗示着指针操作内存不当导致程序崩溃。。。遇到问题后,首先百度了一下,很多篇博客也提到了相同的问题,解决方案几乎都是针对什么ubuntu gcc版本,查看一下自己的gcc版本是4.4而且yum源最新,就觉得这个解决方法不靠谱至少在我的环境中不适用。于是乎又转战到google和stackoverflow寻找答案,http://stackoverflow.com/questions/14172409/buffer-overflow-detected-in-a-program-that-runs-flawlessly-apparently 这里给我了启发,他是在做字符串操作的时候出现的这个问题,让我想到了我用的这个程序应该也是出现了指针错误、内存越界之类的问题。幸运的是DBT2 benchmark是手动编译源码的,所以有src。最后的解决方案就是看源码调试源程序。
src/
client.c
db_threadpool.c
db.c
mysql/dbc_common.c
include/mysql_common.h
程序编译完以后是执行client,所以以client为入口调试程序。由于对源程序不了解,所以直接看源码顺便打上一些输出作为调试信息。
依赖关系为:client.c -> db_threadpool.c -> db.c -> mysql/dbc_common.c......,由于程序中本身就有一些输出,崩溃时观察到db_threadpool.c中的printf点有输出正确地信息,后续就没有输出了,dbc_common.c中的LOG_ERROR_MESSAGE也没有输出,同时在这里也发现了大量的strcpy,它把传入进来的字符串参数值全部strcpy拷贝到mysql_开头的全局变量中,于是在每个strcpy后面都添加printf输出当前字符串。重新编译运行,终于发现了终止的地方,mysql_host这个字符串变量的值没输出。再次打开dbc_common.c才恍然大悟,该文件中定义的几个mysql_全局char数组,都是定长的,比如32个字节,万一我们传入的参数大于31个字符,strcpy必然会出问题,检查参数发现,mysql_host字符串长度不止31,所以这里导致了overflow的bug。我把全局变量mysql_host的长度改成了1024 ,重新编译运行,又报出了定义冲突的问题,原来是在include/mysql_common.h中声明了externt char mysql_host[32],这里也需要改成一样的。最后这个bug便修复了。
返回来重新审视这个bug,仅仅是因为定义一个字符数组时分配的空间不足以容纳字符串,导致了buffer overflow detected的错误,所以我们在程序中对于内存空间的分配一定要掌握好,要么分配足够大的定长空间,要么就malloc动态开辟。他这里单纯地以为作为一个host用IP地址表示的话十几、二十个字符长度就够了,然而却没想到AWS的实例使用了非常长的域名,无法容纳导致程序终止,也是万万没想到会在这和小问题上栽跟头。