Segfault 在使用迭代器遍历 std::list 时发生。

huangapple go评论73阅读模式
英文:

Segfault while iterating through std::list<USER_DEFINE_CLASS> with iterator

问题

你遇到的问题似乎是在尝试使用迭代器遍历std::list<User_Defined_Class>时,当尝试访问第二个迭代器时出现了segmentation fault错误。这个问题可能与你的迭代器操作有关。

你的代码中,你创建了一个TcpServer对象,然后实例化了三个Server对象,并将它们添加到了_servers成员变量中的std::list<Server>中。然后,你使用迭代器遍历这个列表,并打印每个Server对象的内容。

然而,问题可能出现在你遍历列表时,如果_servers列表中没有足够的元素,尝试访问第二个迭代器可能导致segmentation fault。请确保你的列表中至少有两个元素,并检查迭代器的使用是否正确。

此外,请确保你的类的成员函数和构造函数/析构函数实现是正确的,以免导致其他潜在问题。

英文:

I am facing a problem in my program where when I try to iterate through my std::list&lt;User_Defined_Class&gt; with iterator, I get a segmentation fault when I try to access the second iterator.

Here is the full program, first I instantiate 3 servers and set to them random port number for debugging purpose, then I push them into std::list&lt;Server&gt; private member of tcp_servers with the help of the public method pushNewServer who is implemented like so:

void TcpServer::pushNewServer(const Server&amp; server)
{
    _servers.push_back(server);
};

and finally I create an Iterator of the same as my list and iterate until I face the end of my list however when I launch this program I get a segfault.

#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;list&gt;

# define GET 1
# define POST 2
# define DELETE 3
# define SET -1
# define CLEAR -2
# define ALL_METHODS 7

#define bitset(byte,nbit)   (byte |= (1 &lt;&lt; nbit))
#define bitclear(byte,nbit) (byte &amp;= ~(1 &lt;&lt; nbit))
#define bitcheck(byte,nbit) (byte &amp; (1 &lt;&lt; nbit))

class Server;
class Location;
class TcpServer
{
    public:
        TcpServer(const std::string&amp; filename){(void)filename;};
        ~TcpServer(){};

        /*GETTERS*/
        std::list&lt;Server&gt; getServers(void) const {return _servers;};

        /*SETTERS*/
        void pushNewServer(const Server&amp; server){_servers.push_back(server);};
    private:
        TcpServer(const TcpServer&amp; rhs);
        TcpServer&amp; operator=(const TcpServer&amp; rhs);
        TcpServer();
        std::list&lt;Server&gt; _servers;
        /* data */
};




class Location
{
    public:
        Location()
            :_location_options(0),_body_size(0),_index(&quot;&quot;),_root_dir(&quot;&quot;),_uri(&quot;&quot;),_server(0){};
        Location(const Location&amp; rhs)
        {
            _location_options = rhs._location_options;
            _body_size = rhs._body_size;
            _root_dir = rhs._root_dir;
            _index = rhs._index;
            _uri = rhs._uri;
            _sub_locations = rhs._sub_locations;
            _server = rhs._server;
        }
        Location&amp; operator=(const Location&amp; rhs)
        {
            if (this == &amp;rhs) return *this;
            _location_options = rhs._location_options;
            _body_size = rhs._body_size;
            _root_dir = rhs._root_dir;
            _index = rhs._index;
            _uri = rhs._uri;
            _sub_locations = rhs._sub_locations;
            _server = rhs._server;
            return *this;
        }
        ~Location(){};
    
        /*GETTERS*/
        unsigned int&amp;  getLocationsOptions(void) {return _location_options;};
        const unsigned int&amp; getBodySize(void) const {return _body_size;};
        const std::string&amp; getRootDir(void) const {return _root_dir;};
        const std::string&amp; getIndex(void) const {return _index;};
        const std::string&amp; getUri(void) const {return _uri;};
        std::list&lt;Location&gt; getSubLocations(void) const {return _sub_locations;};
        const Server* getServer(void) const {return _server; };

        /*Setters*/
        void    setBodySize(const unsigned int&amp; body)
        {
            _body_size = body;
        };
        void    setIndex(const std::string&amp; index)
        {
            _index = index;
        };
        void    setRootDir(const std::string&amp; root_dir)
        {
            _root_dir = root_dir;
        };
        void    setUri(const std::string&amp; uri)
        {
            _uri = uri;
        };
        void    pushNewLocation(const Location&amp; location)
        {
            _sub_locations.push_back(location);
        };
        void    setServer(Server *server)
        {
            _server = server;
        };

        void    setLocationOption(const unsigned int&amp; nbit, char actions)
        {
            if (actions == SET)
                bitset(_location_options, nbit);
            else if (actions == CLEAR)
                bitclear(_location_options, nbit);
        };

        /*MEMBER FUNCTION*/
        bool    checkBits(const unsigned int&amp; nbit) const
        {
            return (bitcheck(_location_options, nbit) &gt; 0);
        }
    private:
        unsigned int    _location_options;
        unsigned int    _body_size;
        std::string _index;
        std::string _root_dir;
        std::string _uri;
        std::list&lt;Location&gt; _sub_locations;
        Server  *_server;
};


class Server
{
    public:
        Server()
            :_serv_options(0),_port(0),_body_size(0),_root_dir(&quot;&quot;),_index(&quot;&quot;){};
        Server(const Server&amp; rhs)
        {
            _serv_options = rhs._serv_options;
            _body_size = rhs._body_size;
            _port = rhs._port;
            _root_dir = rhs._root_dir;
            _index = rhs._index;
            _server_names = rhs._server_names;
            _locations = rhs._locations;
        }
        Server&amp; operator=(const Server&amp; rhs)
        {
            if (this == &amp;rhs) return *this;
            _serv_options = rhs._serv_options;
            _body_size = rhs._body_size;
            _port = rhs._port;
            _root_dir = rhs._root_dir;
            _index = rhs._index;
            _server_names = rhs._server_names;
            _locations = rhs._locations;
            return *this;
        }
        ~Server(){};

        /*GETTERS*/
        unsigned int  getServOptions(void) const {return _serv_options;};
        const unsigned int&amp; getPort(void) const {return _port;};
        const unsigned int&amp; getBodySize(void) const {return _body_size;};
        const std::string&amp; getRootDir(void) const {return _root_dir;};
        const std::string&amp; getIndex(void) const {return _index;};

        std::list&lt;Location&gt; getLocations(void) const {return _locations;};
        std::list&lt;std::string&gt; getServerNames(void) const {return _server_names;};

        /*Setters*/
        void    setPort(const unsigned int&amp; port)
        {
            _port = port;
        };
        void    setBodySize(const unsigned int&amp; body)
        {
            _body_size = body;
        };
        void    setRootDir(const std::string&amp; root_dir)
        {
            _root_dir = root_dir;
        };
        void    setIndex(const std::string&amp; index)
        {
            _index = index;
        };
        void    pushNewServerName(const std::string&amp; server_name)
        {
            _server_names.push_back(server_name);
        };
        void    pushNewLocation(const Location&amp; location)
        {
            _locations.push_back(location);
        };
        void    setServOption(const unsigned int&amp; nbit, char actions)
        {
            if (actions == SET)
                bitset(_serv_options, nbit);
            else if (actions == CLEAR)
                bitclear(_serv_options, nbit);
        };

        /*MEMBER FUNCTION*/
        bool    checkBits(const unsigned int&amp; nbit) const
        {
            return (bitcheck(_serv_options, nbit) &gt; 0);
        }
    private:
        unsigned int    _serv_options;
        unsigned int    _port;
        unsigned int    _body_size;
        std::string     _root_dir;
        std::string     _index;
        std::list&lt;std::string&gt; _server_names;
        std::list&lt;Location&gt; _locations;
};



int main (int argc, char **argv)
{
    try
    {
        TcpServer tcp_servers(argc &gt; 1 ? argv[1] : &quot;&quot;);
        Server a;
        Server b;
        Server c;
        a.setPort(1500);
        b.setPort(2500);
        c.setPort(3500);
        tcp_servers.pushNewServer(a);
        tcp_servers.pushNewServer(b);
        tcp_servers.pushNewServer(c);
        std::list&lt;Server&gt;::iterator it;
        for (it = tcp_servers.getServers().begin(); it != tcp_servers.getServers().end() ; it++)
        {
            std::cout &lt;&lt; &amp;*it &lt;&lt; std::endl;
            std::cout &lt;&lt; &quot;-----------NEXT_SERV-------------\n\n&quot;;
        }
    }
    catch(const std::exception&amp; e)
    {
        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
    }
    
}

答案1

得分: 3

以下是您要翻译的代码部分:

问题出在 TcpServer::getServers 函数上:

std::list&lt;Server&gt; getServers(void) const {return _servers;};

因为它返回列表 按值,所以循环

for (it = tcp_servers.getServers().begin(); it != tcp_servers.getServers().end() ; it++)

将有两个不同的列表,它将迭代器与之进行比较。

tcp_servers.getServers().begin() 获取的迭代器将针对完全不同的列表,而从 tcp_servers.getServers().end() 获取的迭代器也将如此。

要能够比较迭代器,它们必须都来自完全相同的容器。

简单的解决方案是改为通过引用返回列表:

std::list&lt;Server&gt;&amp; getServers(void) const {return _servers;};

另外,关于默认容器,真的应该使用 std::vector。除非您有非常特定的要求(我在这里没有看到任何要求),不需要使用 std::list

此外,请不要使用显式迭代器 for 循环,除非您对此有非常具体的要求。范围 for 循环 同样有效:

for (auto&amp; server : tcp_servers.getServers())
{
    std::cout &lt;&lt; &amp;server &lt;&lt; '\n';
}
英文:

The problem is with the TcpServer::getServers function:

std::list&lt;Server&gt; getServers(void) const {return _servers;};

Because it returns the list by value, the loop

for (it = tcp_servers.getServers().begin(); it != tcp_servers.getServers().end() ; it++)

will have two different lists that it compares the iterators with.

The iterator you get from tcp_servers.getServers().begin() will be for a totally different list than the iterator you get from tcp_servers.getServers().end().

To be able to compare iterators they must both come from the exact same container.

The simple solution is to return the list by reference instead:

std::list&lt;Server&gt;&amp; getServers(void) const {return _servers;};

On a different note, the default container should really be std::vector. Unless you have very specific requirements (and I don't see any here) there no need for std::list.

Also please don't use explicit iterator for loops unless you have very specific requirements for it. A range for loop would work just as well:

for (auto&amp; server : tcp_servers.getServers())
{
    std::cout &lt;&lt; &amp;server &lt;&lt; &#39;\n&#39;;
}

huangapple
  • 本文由 发表于 2023年4月13日 16:55:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76003538.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定