《从缺陷中学习C/C++》第3章库函数问题,本章主要介绍库函数的使用中会遇到的问题。使用库函数可以降低软件开发的难度,提高代码编写的效率。本节为大家介绍危险的strdup函数。
作者:ymdsg/kfdmt/ymdyg/xqdcc 等来源:人民邮电出版社| 2013-11-28 15:35 3.22 危险的strdup函数
3.22? 危险的strdup函数
代码示例
void?printDup(char?*str) ?{ ?????char?*tmp?=?strdup(str); ?????printf(“%s\n”,?tmp); ?} ?int?main() ?{ ?????char?*ptr?=?”Hello?World!”; ?????printDup(ptr); ?????printf(“Command?to?check?memleak:?valgrind?–tool=memcheck–leak-?check=yes?./a.out\n”); ?????return?0; ?} ?
现象&后果
程序运行一切正常,但用内存检查工具查看时,发现有内存泄漏发生,strdup分配的内存没有被释放。
Bug分析
这里的内存泄漏主要与strdup函数有关。strdup用来实现字符串复制,它的glibc参考实现如下:
char?*?__strdup?(const?char?*s) ?{ ???size_t?len?=?strlen?(s)?+?1; ???void?*new?=?malloc?(len); ???if?(new?==?NULL) ?????return?NULL; ???return?(char?*)?memcpy?(new,?s,?len); ?} ?
由strdup函数实现代码可以看到,strdup会自动分配内存空间,并复制字符串。但strdup只malloc了内存,并没有释放。释放strdup内部动态分配的内存需要由调用者去做,这点在strdup的man手册里明确提到。
一般大家都比较清楚malloc/free要成对使用,但strdup把动态分配内存的事实隐藏在自己内部,如果使用者不了解这个细节,就会造成内存泄漏。
正确的做法是,strdup返回的字符串在使用完之后要及时用free释放掉。
正确代码
void?printDup(char?*str) ?{ ?????char?*tmp?=?strdup(str); ?????printf(“%s\n”,?tmp); ?????free(tmp); ?} ?int?main() ?{ ?????char?*ptr?=?”Hello?World!”; ?????printDup(ptr); ?????printf(“Command?to?check?memleak:?valgrind?–tool=memcheck–leak-?check=yes?./a.out\n”); ?????return?0; ?} ?
编程建议
由于strdup函数有容易忘记释放内存的风险,不推荐使用它。如果想做字符串复制操作,建议直接使用malloc函数加memcpy函数。
33806291