strdup() causing memory leaks?
我已经实现了一个返回字符串的函数。它使用整数作为参数(age),并返回格式化的字符串。
一切正常,除了我有一些疯狂的内存泄漏的事实。我知道strdup()是造成这种情况的原因,但是我试图研究一些修复措施但无济于事。
我的代码是:
1 2 3 4 5 6 7 8
| const char * returnName (int age ) {
char string [30];
sprintf( string ,"You are %d years old", age );
return strdup (string );
} |
Valgrind \\的输出是:
1 2 3 4 5 6
| ==15414== LEAK SUMMARY:
==15414== definitely lost: 6,192 bytes in 516 blocks
==15414== indirectly lost: 0 bytes in 0 blocks
==15414== possibly lost: 0 bytes in 0 blocks
==15414== still reachable: 0 bytes in 0 blocks
==15414== suppressed: 0 bytes in 0 blocks |
对于解决此内存泄漏问题的任何帮助,我们深表感谢。
- 您已经显示了分配的代码,释放的代码在哪里?
-
您是否阅读了strdup的任何文档?
-
代码最终是否free()由returnName()返回的指针?如果没有,则存在泄漏。
-
您有时需要free strdup的结果,这又意味着您需要将return-type更改为just(non- const)char *。
-
我如何在局部变量的函数之外释放局部变量?要回答这个问题-由于上述原因,我没有释放strdup。
-
@ user2832891您返回一个指向分配的存储区的指针,可以将其传递给free。
-
@ user2832891什么是局部变量?您已将strdup的结果返回给调用方,因此函数的调用方应free。
strdup()本质上等同于
因此,使用完字符串后,您需要记住要调用free()。
1 2 3
| const char* name = returnName (20);
/* do stuff with name */
free((void*)name ); |
如果您不拨打free(),则valgrind当然会报告泄漏。
-
下面也向另一位用户询问:如果我在这样的主要方法中打印:printf("%s", returnName(3));那么调用该方法时没有关联诸如name的变量名该怎么办?我将如何释放它呢?谢谢。
-
@ user2832891然后,您导致了内存泄漏。您需要将变量与之关联,以便以后可以free对其进行操作。
-
@PCLuddite您刚刚复制了我的答案吗?
-
@Michi我没有尝试过,但我可以看到您的想法。我将示例更改为较早的编辑,以便进行多种选择。
-
@Michi本着公平竞争的精神,我赞成你的回答。对于任何侵权,我深表歉意。
-
如何将const char*值保留为char*变量? returnName(3)的返回类型是const char*
strdup看起来像这样:
1 2 3 4 5 6 7 8 9 10
| char *strdup (const char *str ){
size_t n = strlen(str ) + 1;
char *dup = malloc(n );
if(dup ){
strcpy(dup , str );
}
return dup ;
} |
如您所见,还涉及到malloc,这意味着在使用strdup动态分配该内存之后的某个时刻,您在不再需要它之后必须free对其进行存储。<铅>
来自man strdup:
Memory for the new string is obtained with
malloc(3), and can be freed with free(3).
因此您需要free由strdup分配和返回的空间。
假设您像这样调用returnName:
1
| const char* str = returnName(3); |
完成str后,您可以像这样free:
需要强制类型转换,因为free需要一个非常量void*。这种显式转换在这里还可以,因为returnName实际上应该返回常量data1。在这里调用free只是一个讨厌的实现细节。
1如对此答案的注释中与@ M.M讨论的那样。
- 如果我在这样的主要方法中进行打印怎么办:printf("%s", returnName(3));,所以在调用该方法时没有关联诸如str之类的变量名-我将如何释放它?
-
const char* str = returnName(3); printf("%s\
", str);
-
希望我可以避免显式声明一个新变量,但我想这是必须要做的。谢谢。
-
尝试完全输入时,出现以下错误:note: expected a€?void *a€? but argument is of type a€?const char *a€? extern void free (void *__ptr) __THROW;
-
@ user2832891 const指针显然无法free d。因此,您需要从函数中返回char*。
-
该函数仍可以返回const char *。常量指针可以被释放。您可能意味着无法释放指向const的指针,但是您可以在调用free之前将指针转换为void *(或char *)。
-
@ M.M我同意,但是该函数如何返回const char*?从const T*到T*的转换不是隐式AFAIK,而且我(可能还有大多数其他C程序员)不喜欢显式转换。
-
许多人也不喜欢使用非常量指针指向不应被修改的数据:)
-
@ M.M但是strdup返回的内存可以修改,对吗?否则,你有道理。
-
可以,但是OP特意设计了他的函数,以便调用者不应该修改返回的字符串。
-
@ M.M是的,似乎合乎逻辑。那么在这种情况下,可以将const char*强制转换为char*。将添加!
1 2 3 4 5
| const char * returnName (int age ) {
char string [30];
sprintf( string ,"You are %d years old", age );
return strdup (string );
} |
的
返回类型是const char*。因此,您不能将返回的值保留为char*类型的变量。将返回的值保存到const char*变量中,并将其保存到char*中,同时将内存free
1 2 3
| const char* retName = returnName (3);
// Use retName
free((char*)retName ); |
内存泄漏的原因不是来自对strdup()的调用,而是因为发布的函数的调用者在完成字符串处理后未能将返回的指针传递给free()。