質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

591閲覧

c++ 待ち行列シミュレーションにおけるメモリリークの発見

mikocchan

総合スコア4

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2022/08/17 06:54

前提

待ち行列シミュレーションをc++を用いて作成しています。
シミュレーションを実行した際に、メモリリークが発生しているであろうことが分かりましたが、発生箇所がわかりません。valgrindなどのメモリリーク検出ツールを使おうと考えましたが、使い方がよくわからなかったです。

実現したいこと

メモリリークの検出

発生している問題・エラーメッセージ

valgrindが導入できない、メモリリーク箇所が見つけられない。
main関数やクラスのソースコードを添付いたします。待ち行列のリストを管理するクラスcustomerCollectionのソースファイルの方(customerCollection.cpp)にメモリリークの原因があるのではと考えているのですが、詳しい場所はわかりませんでした。

該当のソースコード

customerRecord.h

1#ifndef customerRecord_h 2#define customerRecord_h 3 4#include <iostream> 5#include <math.h> 6#include <stdio.h>//NULLの定義 7#include <stdlib.h>//exit()の定義 8//----------------------------------------------ヘッダファイル クラス型をかく 9 10class customerRecord 11{ 12private://class外からのアクセス不可 ここにはメンバ変数を書く メンバ変数は変数名の頭に_もしくはmをつける(ルールは会社により異なる) 13 int _id; // カスタマー番号 14 int _check; // q1到着(0)、q2到着(1)、q2退去()2チェック 15 double _q1arrivalTime; // q1到着時刻 16 double _arrivalTime; // q2到着時刻 17 double _departureTime; // q2退去時刻 18 double _startTime; // q2サービス開始時間 19public://class外からのアクセス可 ここにはメンバ関数を書く。中身はソースファイル(.cpp)に書く。 20 int customerID(); // これを描くことでID(_idのこと)を取得できる。 21 void setcustomerID(int id); // ここでcustomerRecordのidをセット(設定)する。 22 23 int check(); //到着、退去の取得 24 void setCheck(int check); 25 26 double q1ArrivalTime(); 27 void setq1ArrivalTime(double q1arrivalTime); 28 29 double ArrivalTime(); 30 void setArrivalTime(double arrivalTime); 31 32 double DepartureTime(); 33 void setDepartureTime(double departureTime); 34 35 double StartTime(); 36 void setStartTime(double startTime); 37 38 double getTime();//これを描くことで時間を取得できる。 39 40 customerRecord(); //デフォルトコンストラクタ:引数のないコンストラクタ 41 customerRecord(int customerID,int check,double q1ArrivalTime,double ArrivalTime,double DepartureTime,double StartTime); // 引数を持つコンストラクタ 42 ~customerRecord();//デストラクタ 43}; 44 45//---------------------------------------------- 46#endif

customerRecord.cpp

1//ソースファイル:クラスcustomerRecordのメンバ関数の中身を記述 2#include <iostream> 3#include <math.h> 4#include <stdio.h>//NULLの定義 5#include <stdlib.h>//exit()の定義 6 7#include "customerRecord.h" 8 9using namespace std; 10 11//以下変数取得のためのメンバ関数 12int customerRecord::customerID(){//カスタマー番号の取得 13 return _id; 14} 15void customerRecord::setcustomerID(int id){//カスタマー番号の設定 16 _id = id; 17} 18int customerRecord::check(){ 19 return _check; 20} 21void customerRecord::setCheck(int check){ 22 _check = check; 23} 24//追加 25double customerRecord::q1ArrivalTime(){ 26 return _q1arrivalTime; 27} 28void customerRecord::setq1ArrivalTime(double q1arrivalTime){ 29 _q1arrivalTime = q1arrivalTime; 30} 31// 32double customerRecord::ArrivalTime(){ 33 return _arrivalTime; 34} 35void customerRecord::setArrivalTime(double arrivalTime){ 36 _arrivalTime = arrivalTime; 37} 38double customerRecord::DepartureTime(){ 39 return _departureTime; 40} 41void customerRecord::setDepartureTime(double departureTime){ 42 _departureTime = departureTime; 43} 44double customerRecord::StartTime(){ 45 return _startTime; 46} 47void customerRecord::setStartTime(double startTime){ 48 _startTime = startTime; 49} 50//変更 51double customerRecord::getTime(){ 52 if(check() == 0){//q1到着 53 return q1ArrivalTime(); 54 } 55 else if(check() == 1){//q2到着 56 return ArrivalTime(); 57 } 58 else if(check() == 2){//q2退去 59 return DepartureTime(); 60 } 61 else{ 62 cout << "ERROR_getTime"<<endl; 63 exit(1); 64 } 65} 66 67//以下コンストラクタ等 追加 68customerRecord::customerRecord(){//デフォルトコンストラクタ:引数のないコンストラクタ 69 setcustomerID(-1);//全部に-1を設定ー>初期化 70 setCheck(-1); 71 setq1ArrivalTime(-1); 72 setArrivalTime(-1); 73 setDepartureTime(-1); 74 setStartTime(-1); 75} 76customerRecord::customerRecord(int customerID,int check,double q1ArrivalTime,double ArrivalTime,double DepartureTime,double StartTime){//引数を持つコンストラクタ 77 setcustomerID(customerID); 78 setCheck(check); 79 setq1ArrivalTime(q1ArrivalTime); 80 setArrivalTime(ArrivalTime); 81 setDepartureTime(DepartureTime); 82 setStartTime(StartTime); 83} 84customerRecord::~customerRecord(){ 85 //特に処理なし 86}

customerCollection.h

1#ifndef customerCollection_h 2#define customerCollection_h 3 4#include <iostream> 5#include <math.h> 6#include <stdio.h>//NULLの定義 7#include <stdlib.h>//exit()の定義 8#include "customerRecord.h" 9//----------------------------------------------ヘッダファイル クラス型をかく 10 11class customerCollection 12{ 13private: 14 struct customerNode 15 { 16 customerRecord customerData; // カスタマーレコード 17 customerNode *next = NULL; 18 };//構造体の中にクラスと次のクラスに向けたポインタを格納している 19 typedef customerNode *customerList;//構造体customerNodeの名前をcustomerListに変更 そのつながりのことをリストと表現! 20 customerList _listHead; // 連結リストの先頭を示すメンバ変数 21 void deleteList(customerList &listPtr); 22 customerList copiedList(const customerList original);//構造体を複製してるので、コピーコンストラクタとは違う 23public: 24 customerCollection(); // デフォルトコンストラクタ 25 customerCollection(const customerCollection &original){_listHead = copiedList(original._listHead);}//コピーコンストラクタ 26 ~customerCollection();// デストラクタ 27 customerCollection& operator = (const customerCollection &cc); //代入 =という演算子をオーバーロードしている 28 void addRecord(customerRecord newcustomer); 29 void deletecustomer(); 30 int top(); 31 32 int getcustomerID(); 33 int getcheck(); 34 double getq1ArrivalTime();//追加 35 double getArrivalTime(); 36 double getDepartureTime(); 37 double getStartTime(); 38}; 39 40//---------------------------------------------- 41#endif

customerCollection.cpp

1//ソースファイル:クラスcustomerRecordのメンバ関数の中身を記述 2#include <iostream> 3#include <math.h> 4#include <stdio.h>//NULLの定義 5#include <stdlib.h>//exit()の定義 6 7#include "customerCollection.h" 8 9using namespace std; 10 11void customerCollection::deleteList(customerList&listPtr){//リスト内を全て完全に削除=デストラクタ 12 while (listPtr != NULL){ 13 customerNode *temp = listPtr; 14 listPtr = listPtr -> next; 15 delete temp; 16 } 17} 18customerCollection::customerCollection(){//デフォルトコンストラクタ 19 _listHead = NULL; 20} 21/*customerCollection::customerCollection(const customerCollection &original){//コピーコンストラクタ .hの方にもう書いてある 22 _listHead = copiedList(original._listHead); 23}*/ 24customerCollection::~customerCollection(){//デストラクタ 25 deleteList(_listHead); 26} 27void customerCollection::addRecord(customerRecord newcustomer){ 28 customerList x = new customerNode; 29 customerNode *newNode = new customerNode; 30 x = _listHead; 31 newNode -> customerData = newcustomer; 32 if(_listHead == NULL){//何もない状態のとき 33 _listHead = newNode; 34 //delete x; 35 //delete newNode; 36 return; 37 } 38 else if(_listHead->customerData.getTime() > newcustomer.getTime()){//挿入 39 newNode -> next = _listHead; 40 _listHead = newNode; 41 //delete x; 42 //delete newNode; 43 return; 44 } 45 while(1){ 46 if(x -> next == NULL){ 47 x -> next = newNode; 48 newNode -> next = NULL; 49 //delete x; 50 //delete newNode; 51 break; 52 } 53 else if(x -> next -> customerData.getTime() > newcustomer.getTime()){ 54 newNode -> next = x -> next; 55 x -> next = newNode; 56 //delete x; 57 //delete newNode; 58 break; 59 } 60 x = x -> next; 61 } 62} 63void customerCollection::deletecustomer(){//先頭の客のデータを削除=後ろにずらすイメージ 64 customerList x = new customerNode; 65 x = _listHead; 66 if(x == NULL){ 67 exit(1); 68 }//1:異常終了 0:正常終了 69 else if(x -> next == NULL){ 70 _listHead = NULL; 71 //delete x; 72 } 73 else{ 74 _listHead = _listHead->next; 75 //delete x; 76 } 77 delete x; 78} 79int customerCollection::top(){//客がいればtrue 80 if(_listHead != NULL) return true; 81 else return false; 82} 83int customerCollection::getcustomerID(){//先頭のcustomerIDを返す 84 return _listHead->customerData.customerID(); 85} 86int customerCollection::getcheck(){ 87 return _listHead->customerData.check(); 88} 89double customerCollection::getq1ArrivalTime(){ 90 return _listHead->customerData.q1ArrivalTime(); 91} 92double customerCollection::getArrivalTime(){ 93 return _listHead->customerData.ArrivalTime(); 94} 95double customerCollection::getDepartureTime(){ 96 return _listHead->customerData.DepartureTime(); 97} 98double customerCollection::getStartTime(){ 99 return _listHead->customerData.StartTime(); 100}

simulation4.h

1#ifndef simulation4_h 2#define simulation4_h 3 4#include "customerRecord.h" 5#include "customerCollection.h" 6//mu1とmu2を入れると、その時の正規化した平均AoIを導出する。 7//0805のミーティングでのミスを改善する 8 9#include <iostream> 10#include <math.h> 11#include <stdio.h>//NULLの定義 12#include <stdlib.h>//exit()の定義 13#include <random> 14using namespace std; 15//----------------------------------------------ヘッダファイル クラス型をかく 16class simulation{ 17private: 18 double _mu1; 19 double _mu2; 20 double _L2_0_border; 21 double _L2_1_border; 22 double _L2_2_border; 23 24public: 25 double MU1(); 26 void setMU1(double mu1); 27 double MU2(); 28 void setMU2(double mu2); 29 30 double L2_0_Border(); 31 void setL2_0_Border(double L2_0_border); 32 double L2_1_Border(); 33 void setL2_1_Border(double L2_1_border); 34 double L2_2_Border(); 35 void setL2_2_Border(double L2_2_border); 36 37 simulation(double MU1,double MU2,double L2_0_Border,double L2_1_Border,double L2_2_Border);//コンストラクタ 38 double L2_border(int L2,double L2_0_border,double L2_1_border,double L2_2_border); 39 pair<double,double> AoI_return(double mu1,double mu2,double L2_0_border,double L2_1_border,double L2_2_border);//AoIを返すメンバ関数 40 ~simulation();//デストラクタ 41}; 42 43//---------------------------------------------- 44#endif

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

MacOS Monterey ver12.5 を使用しています。
エディタはvscodeです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

c++

1 customerList x = new customerNode; 2 customerNode *newNode = new customerNode; 3 x = _listHead;

1行目で確保したメモリへのポインタが、3行目で上書きされて開放不能になってます。customerList x = _listHead でいいんじゃないでしょうか。


その他気になったところ:

  • データメンバ名を _ で始めるのはダメです。
  • 昨今の C++ では、new delete を使うのをできるだけ避けます。customerNode::nextcustomerNode* ではなく std::unique_ptr<customerNode> に、customerList _listHeadstd::unique_ptr<customerNode> listHead_に、new customerNodestd::make_unique<customerNode>() にしましょう。

投稿2022/08/17 07:09

編集2022/08/17 07:26
int32_t

総合スコア20884

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問