Search code examples
c++polymorphismstdlist

Why this c++ program segfault?


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
}

Solution

  • 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.