0

以下は宿題に関するものです。ペットのプロジェクト タイプのものを拘束します。タスクは、ベクターを使用するように更新することです。私が抱えている問題は次のとおりです。これにより、コア セグメンテーション エラーが発生しますが、valgrind を使用すると、すべての情報を適切に取得できます。

void Table::partyCheckout(void)
{
        if(status == SERVED)
        {
                cout << " ---------------- " << endl;
                cout <<"Table: " << tableId << "\nParty Size: " << numPeople << "\nWaiter: " << waiter->getName() << "\nSummary: " <<endl;
                order->requestSummary();
                cout << "Total: " << endl;
                order->requestTotal();
                cout << " ---------------- " << endl;
                status = IDLE;
        }
        else
        {
                cout << "Error: " << tableId << " ";
                if(numPeople == 0)
                {
                        cout << "No one is at this table." << endl;
                }
                else
                {
                        cout << "This party hasn't been served." << endl;
                }
        }
}

セットアップ: ウェイターと注文をベクトルに保存しています。
実行時: waiter->getName() を実行すると、無効な読み取りであり、デアロケータを介してベクトルによってメモリ位置が解放されたと不平を言います。
この問題に関する私の論理:先を見越して、ベクター自体が再びアクセスされないことを確認し、割り当てを解除します。この時点以降は書き込みを行わないため、メモリの場所はそのまま残ります。場所を読み取ろうとすると、解放されていることがわかります。したがって、無効な読み取りですが、適切なデータを取得します。
ですから、私の質問は 2 つあると思います:
この論理は正しいのでしょうか?
修正するにはどうすればよいですか?

#ifndef HW3_H
#define HW3_H
#include <vector>
#include "Table.h"
#include "Waiter.h"

class hw3
{
private:

        vector<Table> tables;
        vector<Waiter> waiters;
        vector<Order> orders;
public:
        void begin();

};
#endif

.cpp ファイル、ほとんどの割り当て:

 ifstream configFile("config.txt"); //This guy is for initializing things
        string line;

        Menu theMenu;
        getline(configFile, line);
        stringstream intMaker;
        int t1;
        int t2;
        string temp;
        string temp2;
        string temp3;
        while (true)
        {
                getline(configFile, line);
                Tokenizer str(line, " \n");
                if(line =="")
                {


                        break;
                }
                else
                {
                        temp = str.next();
                        temp2 = str.next();
                        intMaker << temp;
                        intMaker >> t1;
                        intMaker.str("");
                        intMaker.clear();
                        intMaker << temp2;
                        intMaker >> t2;
                        intMaker.str("");
                        intMaker.clear();
                        tables.push_back(*(new Table(t1,t2)));


                }


        }

        getline(configFile, line);
        while (true)
        {
                getline(configFile, line);
                Tokenizer name(line, " ");
                string tabl = "";
                //Siphon off the name and the tables.
                temp = name.next();
                tabl = name.next();
                Tokenizer strink(tabl, ",\n");
                int numTables = (int) tables.size();
                Table * tabs[numTables];
                t1 = 0;
                int keepinTabs = 0;
                while(true)
                {
                        string temp2 = strink.next();

                        if (temp2 == "")
                        {

                                 break;
                        }
                        else
                        {
                                 intMaker << temp2;
                                 intMaker >> t1;

                                 intMaker.str("");
                                 intMaker.clear();
                                 for(int i = 0; i < numTables; i++)
                                 {
                                        if(tables.at(i).getTableId() == t1)
                                        {
                                                tabs[keepinTabs] = &tables.at(i);
                                        }
                                 }
                                 keepinTabs++;
                        }

                }

                waiters.push_back(*(new Waiter(temp, tabl, *tabs))); //Waiter(name, list of tables, and an array of table numbers.
                for(int j = 0; j < keepinTabs; j++)
                {
                        for(int i = 0; i < tables.size(); i++)
                        {
                                if(tabs[j]->getTableId() == tables[i].getTableId())
                                {
                                        tables.at(i).assignWaiter(&(waiters.back()));
                                }
                        }
                }
                if(line == "")
                {
                        break;
                }
        }
4

1 に答える 1

1

私が見ることができる複数の問題:

tables.push_back(*(new Table(t1,t2)));

このコードは、タイプ のオブジェクトを動的に割り当て、このオブジェクトのコピーTableを にプッシュし、動的に割り当てられたオブジェクトのアドレスを忘れます。メモリ リークが発生しています。tables

waiters.push_back(*(new Waiter(temp, tabl, *tabs)));

以上、Waiter今回も。

tabs[keepinTabs] = &tables.at(i);

これは、ベクトル内のオブジェクトのアドレスを取得します。合法ですが、非常に壊れやすいです。std::vectorサイズが変更されたとき(たとえば、プッシュしたとき)にメモリ内でコンテンツを移動できます。

これ (または他の場所にある同様のコード) がセグメンテーション違反の原因である可能性があります。オブジェクトを動的に割り当てているので、ポインターだけを保持するようにベクトルを宣言する必要があるかもしれません。

vector<Table*> tables;
vector<Waiter*> waiters;
vector<Order*> orders;

あなたはそれから例えばするでしょうtables.push_back(new Table(t1, t2));。もちろん、deleteベクトルからオブジェクトを削除するときは、動的に割り当てられたオブジェクトを確認する必要があります。別の方法として、スマート ポインターを使用することもできます。たとえば、次のようになります。

vector<std::shared_ptr<Table> > tables;
vector<std::shared_ptr<Waiter> > waiters;
vector<std::shared_ptr<Order> > orders;
于 2012-11-29T15:58:17.613 に答える