gpt4 book ai didi

c - strdup 和内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 17:20:37 26 4
gpt4 key购买 nike

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

例如:下面的代码会导致内存泄漏吗?

void x(char** d, char* s){
*d = strdup(s);
}

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

最佳答案

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

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

 x(&test, "etc");

变量 test 保存了在之前调用 x 时分配的指针的唯一副本。对 x 的新调用会覆盖该指针。那时,指针泄漏。

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

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

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

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

POSIX strdup 函数的行为与此类似:

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 能够为第二次分配。 (但是,垃圾收集器不会在一次分配后启动,除非它在压力测试模式下运行以清除错误。)

现在,如果你真的想通过 realloc 重用内存,那么你可以按照这些行更改你的 x 函数:

#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 C 保留命名空间中,但 stralloc 是一个很好的名称,无法拒绝。)

请注意,界面不同。我们不传递一个指向指针的指针,而是呈现一个类似于 realloc 的接口(interface)。调用者可以检查 null 的返回值以检测分配错误,而不会在这种情况下不方便地用 null 覆盖指针。

main 函数现在看起来像:

int main(void)
{
char *test = strealloc(NULL, "abcd");
test = strealloc(test, "etc");
free(test);
return 0;
}

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

只需要一个 free 来堵住内存泄漏。


* 程序没有丢失引用的对象可能会发生语义内存泄漏。例如,假设一个程序不断地向列表中添加信息,该列表从未用于任何目的并且只是不断增长。

关于c - strdup 和内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20711970/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com