문제

I'm really having a hard time to determine why this program is segfaulting. I am using a std::list containing objects pointer in object Park. Everything seems to work fine but when I use the iterator of the list and try to call some object method, it segfaults.

I discovered that if I modify the type of the std:list<Felid*> to std:list<Felid*>*, there is no more segfault.I would like to understand why this is working ?

I compile this with g++ : g++ -g -Wall -std=c++11 main.cpp

main.cpp :

#include <iostream>
#include <list>

class Felid {
    public:
        void do_meow() {
            this->meow(); // <-- Segfault occurs, why ?
        }
    protected:
        virtual void meow() = 0;
};

class Park {
    public:
        std::list<Felid*> getFelids() {
            return this->felids;
        }

        void add_felid(Felid* f) {
            this->getFelids().push_back(f);
        }

        void listen_to_felids() {
            for (std::list<Felid*>::iterator it = this->getFelids().begin(); it != this->getFelids().end(); it++)
            {
                (*it)->do_meow(); // <-- will Segfault
            }
        }
    protected:
        std::list<Felid*> felids;
};



class Cat : public Felid {
    protected:
        void meow() { std::cout << "Meowing like a regular cat! meow!\n"; }
};

class Tiger : public Felid {
    protected:
        void meow() { std::cout << "Meowing like a tiger! MREOWWW!\n"; }
};



int main() {
    Park* p = new Park();

    Cat* cat = new Cat();
    Tiger* tiger = new Tiger();

    p->add_felid(cat);
    p->add_felid(tiger);

    p->listen_to_felids(); // <-- will Segfault
}
도움이 되었습니까?

해결책

The problem is with the std::list<Felid*> getFelids() method. It's returning the list by value, so every time you call it you get a new copy of the list. You should return a reference with std::list<Felid*>&

The segfault is because your iterator's begin() and end() are from different lists (because you're making a copy each time), so the iterator never reaches the end() of the first list and keeps going through random memory.

Also, the list you're iterating through was just a temporary, so it's gone by the time you try to use the iterator.

다른 팁

std::list<Felid*> getFelids()

This returns a copy of the list. Any changes to it do not affect felids in your class. Change the return type to std::list<Felid*>&

The key issue is you are returning the list by value below than by reference

    std::list<Felid*> getFelids() {
        return this->felids;
    }

Here getFelids does not returns a copy of the std::list and adding felids to that doesn't add to the original class member. When you return by pointer then you are modifying the original class member.

Right way would be return by pointer (std::list<>* ) or by reference (std::list<>&)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top