-2

この単純なコードを実行したときに得られる出力を理解するのに少し苦労しています

#include <vector>
#include <iostream>
#include "LxUNIXsys.h"
using namespace std;

int main(int argc, char** argv) {

  //memory management class
  LxUNIXsys mem_manager;

  vector <double*> vec;

  mem_manager.DumpMemoryInfo();getchar();
  for(int i =0; i < 3; i++) vec.push_back(new double (3));
  for(int i =0; i < vec.size(); i++) cout << *vec[i] << endl;
  mem_manager.DumpMemoryInfo();getchar();
  for(int i =0; i < vec.size(); i++) delete vec[i];
  vec.clear();
  for(int i =0; i < 3; i++) cout << *vec[i] << endl;
  cout <<"size of vec " <<vec.size() << endl;
  mem_manager.DumpMemoryInfo();

  return 0;
}

LxUNIXsys は、メモリ ダンプに使用しているクラスであり、そこから呼び出しているメソッドは次のとおりです。

void LxUNIXsys::DumpMemoryInfo() {

  pid_t id = getpid();
  //  cout << "id = " << id << endl;
  stringstream ss("");
  ss << "pmap -d " << id  << " | grep private ";
  //  cout << ss.str().c_str() << endl;
  cout << "Memory dump: [pid = " << id << " ] " << flush; system(ss.str().c_str());
}

私が得ている出力は次のとおりです。

Memory dump: [pid = 17012 ] mapped: 51476K    writeable/private: 7452K    shared: 0K

3
3
3
Memory dump: [pid = 17012 ] mapped: 51480K    writeable/private: 7456K    shared: 0K

3
3
3
size of vec 0
Memory dump: [pid = 17012 ] mapped: 51480K    writeable/private: 7456K    shared: 0K

したがって、基本的にはポインターを削除しましたが、情報はまだそこにあるだけでなく、後でアクセスできますclear()

vec を使用して削除しようとしましdelete[]たが、結果は同じです。

PS: スマート ポインターの存在は知っていますが、このコードが期待どおりに動作しない理由を知りたいです。

PPS: 未定義の動作については知っています。クリア後のアクセスについては忘れてください。通常のポインターを削除するときのように、すぐにメモリを解放する効果的な方法が必要です。

4

3 に答える 3

4

未定義の動作があります。std::vectorこれは、存在しない要素にアクセスしたことが原因です。未定義の動作とは、何でも起こり得ることを意味します。破壊されたはずのオブジェクトがまだそこにあるように見えることさえあります。

C++ 標準では、オペレーティング システムがメモリの割り当てと割り当て解除を管理する方法については何も述べていません。プログラムが何に依存できるかについてのルールを与えるだけです。これら 3 つdoubleの s に割り当てられたメモリが、OS によって要求されたよりも少し遅れて実際に回収されなかったという理由はありません。あなたはもうそれに頼ることはできません。信頼できる唯一のことは、 の境界外にアクセスしてはならないということですstd::vector

これがまさに、これが標準で未定義の動作として指定されている理由です。これにより、オペレーティング システムまたは環境にメモリ管理を実行する余裕が与えられますが、プログラムには明確に定義された動作に依存するルールが与えられます。

于 2013-04-09T10:08:46.607 に答える
1

フリー ストアから割り当てられたメモリを削除しても、メモリがオペレーティング システムに返されたり、アクセスできなくなったりする保証はありません。通常、小さな割り当てはプロセス内のヒープによって管理されます。システムから大きな塊を割り当て、その小さな部分を割り当てます。削除されたメモリはそのヒープに戻されます。これは、割り当てごとにシステムにアクセスするよりもはるかに効率的です。

これは、削除されたメモリがまだアクセス可能であり、再利用されるまで、削除されたときにそこにあったデータが含まれている可能性があることを意味します。したがって、それにアクセスすると、明確に定義されたエラーではなく、未定義の動作が発生します。

于 2013-04-09T10:14:02.373 に答える
0

問題は、ベクトルの読み方だと思います:

for(int i =0; i < 3; i++)

この行を使用すると、ベクトルの終わりを超えて読み取っています。コンテンツが削除されても、しばらくはメモリに残る場合があります。これは、いったん削除されると、それらの位置に保持されているものが削除前に保存されていたものであることを確認できなくなりますが、保存したものである可能性があることを意味します。

HD からファイルを削除するようなものです。ビットは実際には書き換えられるまでそこにあり、未使用として設定されているだけです。

于 2013-04-09T10:12:11.940 に答える