首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >strdup和内存泄漏

strdup和内存泄漏
EN

Stack Overflow用户
提问于 2013-12-21 05:07:57
回答 3查看 10.8K关注 0票数 7

strdup是否每次都会分配另一个内存区并创建另一个指针?

例如:以下代码是否会导致内存泄漏?

代码语言:javascript
复制
void x(char** d, char* s){
    *d = strdup(s);
}

int main(){
    char* test = NULL;
    x(&test, "abcd");
    x(&test, "etc");
    return 0;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-12-21 05:16:54

是的,程序会泄漏内存,因为它会分配对象,然后丢失对它们的引用。

第一次发生这种情况是在队列中:

代码语言:javascript
复制
 x(&test, "etc");

变量test保存了在之前的x调用中分配的指针的一个也是唯一的副本。对x的新调用将覆盖该指针。在这一点上,指针泄漏。

这就是内存泄漏的含义:丢失对现有的动态分配的存储的所有引用。

第二次泄漏发生在main函数返回时。此时,test变量被销毁,该变量保存指向"etc"字符串副本的指针的唯一副本。

有时在C程序中,我们有时不关心第二种类型的泄漏:程序终止时不释放的内存,但不会在循环中反复分配(因此它不会导致失控的内存增长问题)。

如果程序被集成到另一个程序中(例如,作为共享库),其中原始的main函数变成了可以在同一程序环境中重复调用的启动函数,那么这两个泄漏都会变成问题。

POSIX strdup函数的行为类似于以下内容:

代码语言:javascript
复制
char *strdup(const char *orig)
{
   size_t bytes = strlen(orig) + 1;
   char *copy = malloc(bytes);
   if (copy != 0)
     memcpy(copy, orig, bytes);
   return copy;
}

是的,它每次都分配新的存储空间。

如果您的C映像中有一个垃圾收集器(例如Boehm),那么泄漏的存储可能会被回收,因此strdup能够重用相同的内存进行第二次分配。(然而,垃圾收集器不会在一次分配后就开始工作,除非它是在压力测试模式下运行的,以便清除bug。)

现在,如果您想实际重用realloc的内存,那么可以按照以下方式更改您的x函数:

代码语言:javascript
复制
#include <stdlib.h>
#include <string.h>

void *strealloc(char *origptr, char *strdata)
{
    size_t nbytes = strlen(strdata) + 1;
    char *newptr = (char *) realloc(origptr, nbytes); /* cast needed for C++ */
    if (newptr)
      memcpy(newptr, strdata, nbytes);
    return newptr;
}

(顺便说一下,以str开头的外部名称在ISO保留的名称空间中,但是strealloc是一个很好的名称,无法拒绝。)

注意,接口是不同的。我们不传入指针对指针,而是提供一个realloc-like接口。调用者可以检查null的返回值以检测分配错误,而不会在这种情况下将指针不便地改写为null。

main函数现在如下所示:

代码语言:javascript
复制
int main(void)
{
    char *test = strealloc(NULL, "abcd");
    test = strealloc(test, "etc");
    free(test);
    return 0;
}

和以前一样,没有错误检查。如果第一个strealloc失败,则test为null。这不是因为它无论如何都会被覆盖,并且strealloc的第一个参数可能是空的。

只需要一个free就可以堵住内存泄漏。

票数 9
EN

Stack Overflow用户

发布于 2013-12-21 05:12:27

是的,它会分配内存,如果你不释放它就会泄漏。从man page

strdup()函数返回一个指向新字符串的指针,该字符串与字符串s重复。新字符串的内存是通过malloc(3)获得的,可以通过free(3)释放。

new_s = strdup(s)本质上等同于:

代码语言:javascript
复制
new_s = malloc(strlen(s)+1);
strcpy(new_s, s);
票数 4
EN

Stack Overflow用户

发布于 2013-12-21 05:59:40

考虑一下strdup的以下定义

代码语言:javascript
复制
#include <string.h>
char *strdup(const char *string);

strdup通过调用mallocstring的副本保留存储空间。此函数的字符串参数应包含一个标记字符串末尾的null字符(\0)。记住释放调用strdup时保留的存储空间。

您必须自己free该字符串。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20711970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档