6

I am trying the new features of c++11 and I found an issue. This is my code:

#include <iostream>
#include <list>
#include <string>

using namespace std;

class A {
public:
        int f (list<string> a, list<string> b={})
        {
            cout << a.size() << endl;
            cout << b.size() << endl; // This line!!!
            return 0;
        }
};

int main ()
{
    A a;
    list<string> l{"hello","world"};
    a.f(l);
    return 0;
}

the execution stuck at "This line!!!" line. I continue debugging and it looks like the problem is here.

       /**  Returns the number of elements in the %list.  */
       size_type
       size() const _GLIBCXX_NOEXCEPT
       { return std::distance(begin(), end()); }

I compile my program in this way:

g++ -std=c++11 -ggdb3 -fPIC -o test TestlistInit.cpp

I am using this version of g++:

g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

thanks in advance!!!

Eze Velez
  • 351
  • 1
  • 2
  • 6
  • 3
    I get same problem on 4.7.3, interestingly just replacing `list b = list()` works. But yeah, seems like a gcc bug. – Barry Oct 30 '14 at 15:51
  • 2
    Definitely a bug. You get a [segmentation fault](http://coliru.stacked-crooked.com/a/b1764458721a56fc) when you return it from a function as a default argument. And look what happens [when the list contains elements.](http://coliru.stacked-crooked.com/a/fa7a009908546074) – David G Oct 30 '14 at 16:17
  • incredible that such elementary bugs are still in 4.8.2 ... – Walter Oct 30 '14 at 16:49
  • This seems to be working on g++ 4.9.1 (on Debian) – jmajnert Nov 14 '14 at 22:17

1 Answers1

2

To find the cause, enable debug symbols, and when you get to first line, we first check contents of b, which looks like this (the value will be different) In this case I used Code::Blocks "Watch" option.

b.M_Impl._M_node._M_next = 0x7fffffffe370
b.M_Impl._M_node._M_prev = 0x7fffffffe370

Then use debugger option to "Step into" once we hit our b.size line.

Eventually this will take us to stl_iterator_base_funcs.h

At start we can see first & last are same:

__first._M_node = 0x7fffffffe370
__last._M_node = 0x7fffffffe370

 while (__first != __last)
{
  ++__first;
  ++__n;
}

Stepping into ++__first we can see it does this in stl_list.h :

_Self&
operator++()
{
_M_node = _M_node->_M_next;
return *this;
}

_M_node and and _M_node->_M_next are the same, so __first never increments, and .size() is caught in endless loop.

Malcolm McCaffery
  • 2,468
  • 1
  • 22
  • 43