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() 时,它会抱怨这是一次无效的读取,并且内存位置已被向量通过释放程序释放。
我对此事的逻辑:它向前看,发现向量本身不再被访问,因此将其释放。由于在此之后我不再写,内存位置保持不变。当它尝试读取它看到它已被释放的位置时,因此读取无效,但它仍然获得适当的数据。
所以我的问题是,我想有两个方面:
这个逻辑听起来对吗?
我应该怎么做才能修复它?

#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 回答