我正在编写一个函数来加载txt文件并返回一个const char * 下面的函数有效,我的问题是如果我不存储* pS然后调用delete pS会导致内存泄漏吗?
const char* loadFile(string fname)
{
string line,text;
ifstream in(fname);
while(std::getline(in, line))
{
text += line + "\n";
}
string *pS = new string(text);
const char* data = pS->c_str();
return data;
}
该函数在我的代码中使用如下
static const char* pVS;
...
pVS = loadFile("VS.txt");
...
delete pVS;
这会删除字符串吗?
答案 0 :(得分:6)
“这会删除字符串吗?”
否。它会尝试删除std::string
的基础字符存储,从而产生未定义的行为。
即使它成功释放了该存储,也有其他std::string
成员无法处理,所以是的,除了未定义的行为之外,还有内存泄漏。
解决方案:将您的函数更改为返回std::string
对象。或者,您可以返回包含行的std::vector<std::string>
,这似乎比添加"\n"
更合理。
new
或new[]
,请确保:
new
次delete
次呼叫和new[]
,都有适当的delete[]
来电。(请注意,这可能比看起来更难......尤其是当您处理容易出错的代码而您仍然需要处理所有可能的返回路径时〜这是它始终存在的主要原因之一最好使用RAII and smart pointers in C++)
答案 1 :(得分:1)
此函数确实会导致内存泄漏,并且在您显示的代码中使用将调用Undefined Behavior来启动。
该函数导致泄漏,因为您动态分配std::string
(存储在pS
中的那个),然后在loadFile
返回后丢失其地址。没有办法再释放这个字符串了,所以它已经泄露了。
此代码:
pVS = loadFile("VS.txt");
...
delete pVS;
更糟糕。您正在获取未通过new
分配的指针(来自c_str()
),并且您正在调用delete
。这是未定义的行为(很可能是内存损坏),纯粹而简单。
正确的做法是更改功能并返回std::string
:
string loadFile(string fname)
{
string line,text;
ifstream in(fname);
while(std::getline(in, line))
{
text += line + "\n";
}
return text;
}
如果来电者需要const char*
,他们可以自己拨打c_str()
。
答案 2 :(得分:0)
使用
return strdup(text.c_str());
结果是可删除的。当您返回char *时,您将无法避免执行自己的内存管理。更好的方法是返回std::string
。
答案 3 :(得分:0)
为了避免内存泄漏和未定义的行为,而不是返回char*
,请返回string
。
std::string loadFile(string fname)
{
// ...
string retval (text);
// ...
return retval;
}
按值返回string
,但在优化下,编译器通常会忽略副本。
如果您绝对必须返回char*
,请执行以下操作:
const char* loadFile(string fname)
{
string line,text;
ifstream in(fname);
while(std::getline(in, line))
{
text += line + "\n";
}
string retval(text);
char* data = new char [retval.length()+1];
strcpy (retval.c_str(), data);
return data;
}
请记住,在另一方面,您必须delete
这个指针,这意味着使用delete []
:
int main()
{
const char* data = loadFile (...);
delete [] data;
}