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"


メモリ リークを回避するには:
  • 可能な場合は常に動的割り当てを回避し、
  • それが不可能で、newまたはを使用する必要がある場合は、次のnew[]ことを確認してください。
    • new適切なdelete呼び出しがあるたびに
    • すべてnew[]に適切なdelete[]呼び出しがあります。

    (これは思ったよりも難しいかもしれないことに注意してください...特に、エラーが発生しやすいコードを扱っているときに、考えられるすべてのリターン パスを処理する必要がある場合は、これが常に使用することが望ましい主な理由の 1 つです。C++ の RAII とスマート ポインター)

于 2013-10-11T12:47:41.917 に答える
1

この関数は実際にメモリ リークを引き起こします。表示されたコードで使用すると、未定義の動作が呼び出されて起動します。

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

メモリ リークと未定義の動作を回避するには、 を返す代わりに、char*を返しstringます。

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

This returns a string by value, but under optimization the compiler will often elide the copy.

If you absolutely must return a char*, then do it right:

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;
}

Remember that on the other side of this you will have to delete this pointer, which means using 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 に答える