Zac*_*ack 6 c memory-leaks strdup
strdup是否每次都分配另一个内存区域并创建另一个指针?
例如:以下代码是否导致内存泄漏?
void x(char** d, char* s){
*d = strdup(s);
}
int main(){
char* test = NULL;
x(&test, "abcd");
x(&test, "etc");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是的,如果您不释放它,它会分配内存并泄漏。从手册页:
strdup ()函数返回一个指向新字符串的指针,该新字符串是字符串 s 的重复项。新字符串的内存是通过malloc(3)获得的,并且可以通过free(3)释放。
new_s = strdup(s)
本质上相当于:
new_s = malloc(strlen(s)+1);
strcpy(new_s, s);
Run Code Online (Sandbox Code Playgroud)
是的,程序泄漏内存,因为它分配对象,然后丢失对它们的引用.
第一次发生这种情况是在线:
x(&test, "etc");
Run Code Online (Sandbox Code Playgroud)
该变量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;
}
Run Code Online (Sandbox Code Playgroud)
是; 它每次都分配新的存储空间.
如果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;
}
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,从开头的外部名称str
是在ISO C保留的命名空间中,但是strealloc
拒绝拒绝这个名称.)
请注意,界面不同.我们不传入指向指针的指针,而是呈现一个类似realloc
的接口.调用者可以检查null的返回值以检测分配错误,而不会在这种情况下用指针不方便地覆盖指针.
该main
功能现在看起来像:
int main(void)
{
char *test = strealloc(NULL, "abcd");
test = strealloc(test, "etc");
free(test);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
像以前一样,没有错误检查.如果第一个strealloc
失败,test
则为null.这不是因为它无论如何都会被覆盖,并且第一个参数strealloc
可能为null.
free
插入内存泄漏只需要一个.
归档时间: |
|
查看次数: |
7443 次 |
最近记录: |