如何在使用strdup后释放内存?

5

我有这样一个类:

class Kot{
public:
    string name;
};

我创建了一个实例:
Kot* kot = new Kot;
kot->name = "John";

接下来我想创建一个字符串的副本:

string name;
name = strdup(kot->name.c_str());

我使用strdup是因为我想要删除kot并仅使用name变量。 但由于name的内存分配,我有5字节的内存泄漏。 如何安全地释放它?我尝试过delete &name,但是出现了:

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

1
如果你在编写C++代码,不要使用strdup,而是直接分配给一个新的字符串,例如name = kot->name;,这样你就得到了一份拷贝。 - AndersK
3个回答

6
你可能发现了一个5字节的内存泄漏,但这并不是由于字符串造成的。
每次调用strdup都会创建一个大小与字符串长度匹配的新char[]。你应该将其绑定到一个原始指针char*上,并在某个时刻删除它。
相反,你所做的是创建了一个临时char*指针。我们为了方便称其为temp。 然后将temp字符串传递给std::string的构造函数。std::string又复制了一份,使得原始的temp保持不变。
然后temp指针就消失了,没有正确清除内存。
最后,当std::string对象被销毁时,它会正确地清除自己的私有副本。但之前被temp指针指向的内存却从未被释放。
一个快速的解决方法是:
char* temp = strdup(kot->name.c_str());
name = temp;
free(temp);

然而,你甚至不需要这样做!如果你将一个std::string对象分配给另一个,你已经制作了其内容的适当副本。因此:

name = kot->name;

很可能您已经在尝试达到的目标是完全一样的——在您的name内制作一个kot->name的副本。在这种情况下,namekot->name将成为两个完全独立的字符串,具有相同(复制的)内容。从那时起,更改/删除一个不会影响另一个。


name = kot->name; 这是一个不好的建议,因为我想要 delete kot 并且只使用 name 变量。那么在这种情况下,我必须使用 strdup 吗? - Kenenbek Arzymatov
1
@RomaKarageorgievich: 你可以删除kot而不影响已分配的名称。C++的字符串是适当的类,可以管理它们自己的内存。特别地,赋值name=kot->name将创建一个新的文本副本,与存储在kot->name中的副本完全独立。 - celtschk

4
你应该使用free(),而不是delete
根据标准文档
strdup()函数将返回一个指向新字符串的指针,该字符串是指向s的副本。返回的指针可以传递给free()。如果无法创建新字符串,则返回空指针。

1
@RomaKarageorgievich free(&name) 也会给我一个错误。那么 &name 是什么?&name 不是从 strdup() 返回的值。 - Andrew Henle

1
这里有一个内存泄漏:
name = strdup(kot->name.c_str());

由于您从未释放由strdup分配的内存,因此会出现此问题。
为避免此问题,您可以简单地从kot->name构建name:
name = kot->name;

不,我想要完全复制 kot->name 字符串。 - Kenenbek Arzymatov
@RomaKarageorgievich 在您的理解中,什么是完全重复? - Edgar Rokjān
@Roma Karageorgievich:但是“完全重复”正是name = kot->name所创建的。您的strdup在这方面并没有改变任何事情,除了创建内存泄漏。 - AnT stands with Russia
如果你真的想要一个完全相同的副本,那么你应该使用name=std::move(kot->name)。但前提是你要放弃kot,因为kot->name将包含未定义字符串。 - Mika Lindqvist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接