将 at() 与自定义对象的向量一起使用时的分割错误

Segmentation Fault when using at() with vector of custom objects

本文关键字:一起 错误 分割 向量 自定义 对象 at      更新时间:2023-10-16

我正在创建一个应用程序来跟踪书店库存。它将文件路径带到包含信息的文本文件作为 main 的参数。我遇到的问题似乎是每当我尝试访问用于存储 Item 对象的类状态向量清单的元素时。首先是类标头,然后是方法定义,然后是 main。提前谢谢。

    #ifndef _BOOKSTORE_H_
    #define _BOOKSTORE_H_
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <iterator>
    #include <stdlib.h>
    #include "Item.h"
    #include "Paperback.h"
    #include "Hardcover.h"
    #include "Audiobook.h"
    #include "Ebook.h"
    using namespace std;
    class Bookstore {
    //States
    private:
        vector<Item*> inventory;
    //Behaviors
    public: 
        Bookstore();
        void loadInventory(const char*);
        void searchInventory(string);
        unsigned int inventorySize();
        void printInventory();
        vector<string> split(string);
    };
    #endif

    #include "Bookstore.h"
    Bookstore::Bookstore() {}
    void Bookstore::loadInventory(const char* filepath) {
        string ty = "";
        string ti = "";
        string au = "";
        string pri = "";
        string f = "";
        string cd = "";
        string pro = "";
        string line;
        ifstream ifs;
        ifs.open (filepath);
        if (ifs.is_open()) {
            while (ifs.good()) {
                ty = "";
                ti = "";
                au = "";
                pri = "";
                f = "";
                cd = "";
                pro = "";
                getline(ifs, line);
                if (line.compare("Paperback") == 0) {
                    ty = "Paperback";
                    getline(ifs, line);
                    ti = line;
                    getline(ifs, line);
                    au = line;
                    getline(ifs, line);
                    pri = line;
                    Paperback p(ty, ti, au, pri);
                    inventory.push_back(&p);
                }
                if (line.compare("Hardcover") == 0) {
                    ty = "Hardcover";
                    getline(ifs, line);
                    ti = line;
                    getline(ifs, line);
                    au = line;
                    getline(ifs, line);
                    pri = line;
                    getline(ifs, line);
                    f = line;
                    Hardcover h(ty, ti, au, pri, f);
                    inventory.push_back(&h);
                }
                if (line.compare("Audio") == 0) {
                    ty = "Audio";
                    getline(ifs, line);
                    ti = line;
                    getline(ifs, line);
                    au = line;
                    getline(ifs, line);
                    pri = line;
                    getline(ifs, line);
                    cd = line;
                    Audiobook a(ty, ti, au, pri, cd);
                    inventory.push_back(&a);
                }
                if (line.compare("Electronic") == 0) {
                    ty = "Electronic";
                    getline(ifs, line);
                    ti = line;
                    getline(ifs, line);
                    au = line;
                    getline(ifs, line);
                    pri = line;
                    getline(ifs, line);
                    pro = line;
                    Ebook e(ty, ti, au, pri, pro);
                    inventory.push_back(&e);            
                }
            }
        }
        ifs.close();
        cout << inventory.size() << endl;
        for (unsigned int i=0; i<inventory.size(); i++) {
            inventory.at(i)->printItem();
        }
    }
    void Bookstore::searchInventory(string query) {
        vector<string> searchStr;
        int count;
        string currentStr;
            for (unsigned int i=0; i<inventory.size(); i++) {
                    currentStr = inventory.at(i)->getTitle();
                    searchStr = split(currentStr);
                    for(unsigned int j = 0; j < searchStr.size(); j++) {
                        if (searchStr[j].compare(query)==0) {
                            inventory.at(i)->printItem();
                            count++;
                        }
                    }
                    currentStr = inventory.at(i)->getAuthor();
                    searchStr = split(currentStr);
                    for(unsigned int j = 0; j < searchStr.size(); j++) {
                        if (searchStr[j].compare(query)==0) {
                            inventory.at(i)->printItem();
                            count++;
                        }
                    }
                    if ((i==(inventory.size()-1))&&(count==0)) {
                        cout << "Sorry, no matching results were found." << endl;
                    } else if ((i==(inventory.size()-1))&&(count!=0)) {
                        cout << "Query complete." << endl;
                    }
            }
    }
    unsigned int Bookstore::inventorySize() {
        unsigned int num = inventory.size();
        return num;
    }
    void Bookstore::printInventory() {
        for (unsigned int i = 0; i < inventory.size(); i++) {
            inventory.at(i)->printItem();       
        }
    }
    vector<string> Bookstore::split(string s) {
        vector<string> pieces;
        istringstream iss(s);
        copy(istream_iterator<string>(iss), istream_iterator<string>(),
            back_inserter<vector<string> >(pieces));
        return pieces;
    }
    #include "Bookstore.h"
    int main(int argc, char** argv) {
        Bookstore current;
        if (argc==2) {
            current.loadInventory(argv[1]);
        }
        cout << current.inventorySize() << endl;
        //Initialize variables
        char status = 'R';
        string input = "";
        int iter = 1;
        //Run application until quit
        while (status=='R') {
            //Provide menu
            if (iter==1) {
                cout << "Welcome to Bookstore Inventory 9000." << endl;
            }
            if (current.inventorySize()==0) {
                    cout << "There are no entries!" << endl;
                    status = 'Q';
            } else {
                cout << "Would you like to (V)iew all, (S)earch, or (Q)uit?" << endl;
                getline(cin, input);
                if (input.compare("V")==0) {
                    current.printInventory();       
                } else if (input.compare("S")==0) {
                    cout << endl;
                    cout << "What are you looking for?" << endl;
                    getline(cin, input);
                    current.searchInventory(input);
                    cout << endl;
                } else if (input.compare("Q")==0) {
                    status = 'Q';
                    cout << "Thank you for perusing our inventory. Goodbye." << endl;
                } else {
                    cout << endl;
                    cout << "This is not a valid choice. Please try again." << endl;
                    cout << endl;
                }
            }
            iter++;
        }
    return -1;
    }

你的问题不在于at()。 你的问题是你存储了一个局部变量的地址,然后你使用该指针,即使局部变量不再存在。

具体来说,在loadInventory中,这里有一个例子:

 if (line.compare("Paperback") == 0) {
                ty = "Paperback";
                getline(ifs, line);
                ti = line;
                getline(ifs, line);
                au = line;
                getline(ifs, line);
                pri = line;
                Paperback p(ty, ti, au, pri);
                inventory.push_back(&p);
            }

请注意倒数第二行如何创建名为"p"的局部(堆栈)变量。 在最后一行中,您获取该局部变量的地址并将其存储起来。 一旦代码命中上面引用中的最后一个大括号,名为"p"的变量就会消失,向量中的指针就不再有用了。

一种可能的解决方案是动态分配:

Paperback* p = new Paperback(ty, ti, au, pri);
inventory.push_back(p);

请注意,如果执行此操作,则必须在inventory向量完成这些指针后自行删除这些指针。

相关文章: