4

我正在编写一个函数来加载一个 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;

这会删除字符串吗?

4

4 回答 4

7

“这会删除字符串吗?”

不会。它会尝试删除std::string产生未定义行为的基础字符存储。
即使它成功释放了该存储,也有其他std::string成员不会处理,所以是的,除了未定义的行为之外,还有内存泄漏

解决方案:将您的函数更改为返回std::string对象。或者,您可能会返回std::vector<std::string>包含行,这似乎比添加更合理"\n"


为避免内存泄漏:
  • 尽可能避免动态分配,并且
  • 当不可能并且您必须使用newornew[]时,请确保:
    • 对于每new一个适当的delete电话和
    • 对于每new[]一个适当的delete[]呼叫。

    (请注意,这可能比看起来更难......特别是当您处理容易出错的代码时,您仍然需要处理每一个可能的返回路径〜这是为什么总是首选使用它的主要原因之一C++ 中的 RAII 和智能指针

于 2013-10-11T12:47:41.917 回答
1

此函数确实会导致内存泄漏,并且在您显示的代码中使用将调用未定义的行为来启动。

该函数会导致泄漏,因为您动态分配 a 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()自己。

于 2013-10-11T12:50:15.607 回答
1

为了避免内存泄漏和未定义的行为,而不是返回 a char*,返回 a string

std::string loadFile(string fname)
{
  // ...
   string retval (text);
   // ...
   return retval;
}

这会按值返回 a string,但在优化下,编译器通常会省略副本。

如果您绝对必须返回 a 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;
}

请记住,在另一方面,您将不得不指向deletethis 指针,这意味着使用delete []

int main()
{
  const char* data = loadFile (...);
  delete [] data;
}
于 2013-10-11T12:54:20.220 回答
0

采用

return strdup(text.c_str());

结果是可删除的。当您返回一个 char* 时,您将无法避免自己进行内存管理。更好的方法是只返回一个std::string.

于 2013-10-11T12:49:29.837 回答