0

I have an unordered_map named nodes. It is declared as follows:

unordered_map<T,shared_ptr<Vertex<T>>> nodes

Vertex is a class declared as follows:

template<typename T>
struct Vertex {

    Vertex(T pLabel) : label(pLabel) {};

    void addEdge(T destination,int weight) {
        edges[destination] = weight;
    }

    T label;
    unordered_map<T, int> edges;
};

I have a method that accepts the unoredered_map of the vertices as follows.

template<typename T>
void getMinSpanningTree(unordered_map<T,shared_ptr<Vertex<T>>>& nodes, T first, int infinityMarker) {

    cout << nodes.size() << endl;

    if(nodes.size() == 0) {
        return;
    }
    ...
    ...

When I stop the execution in LLDB and type the following:

(lldb) expr nodes.size()

I get the following output:

(lldb) expr nodes.size()
error: Couldn't lookup symbols:
  __ZNKSt3__113unordered_mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_10shared_ptrI6VertexIS6_EEENS_4hashIS6_EENS_8equal_toIS6_EENS4_INS_4pairIKS6_SA_EEEEE4sizeEv

So, I'm not sure how to make the debugger output the answer the correctly. standard output for the following lines, print 5 in the output console:

cout << nodes.size() << endl;

Here, is how I'm using the function and the classes:

int main(int argc, const char * argv[]) {

    shared_ptr<Vertex<string>> v1 = make_shared<Vertex<string>>("V1");
    shared_ptr<Vertex<string>> v2 = make_shared<Vertex<string>>("V2");
    shared_ptr<Vertex<string>> v3 = make_shared<Vertex<string>>("V3");
    shared_ptr<Vertex<string>> v4 = make_shared<Vertex<string>>("V4");
    shared_ptr<Vertex<string>> v5 = make_shared<Vertex<string>>("V5");

    v1->addEdge("V2", 1);
    v1->addEdge("V3", 3);

    v2->addEdge("V1", 1);
    v2->addEdge("V3", 3);
    v2->addEdge("V4", 6);

    v3->addEdge("V1", 3);
    v3->addEdge("V2", 3);
    v3->addEdge("V4", 4);
    v3->addEdge("V5", 2);

    v5->addEdge("V2", 3);


    unordered_map<string,shared_ptr<Vertex<string>>> vertices;
    vertices[v1->label] = v1;
    vertices[v2->label] = v2;
    vertices[v3->label] = v3;
    vertices[v4->label] = v4;
    vertices[v5->label] = v5;

    getMinSpanningTree(vertices,v1->label,numeric_limits<int>::max());

    return 0;
}

Printing the nodes, seems to dump everything:

(std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > > >) $0 = size=5 {
  [0] = {
    __cc = {
      first = "V5"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208c68 strong=2 weak=1 {
        __ptr_ = 0x0000000100208c68
      }
    }
    __nc = {
      first = "V5"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208c68 strong=2 weak=1 {
        __ptr_ = 0x0000000100208c68
      }
    }
  }
  [1] = {
    __cc = {
      first = "V4"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208748 strong=2 weak=1 {
        __ptr_ = 0x0000000100208748
      }
    }
    __nc = {
      first = "V4"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208748 strong=2 weak=1 {
        __ptr_ = 0x0000000100208748
      }
    }
  }
  [2] = {
    __cc = {
      first = "V2"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208c08 strong=2 weak=1 {
        __ptr_ = 0x0000000100208c08
      }
    }
    __nc = {
      first = "V2"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208c08 strong=2 weak=1 {
        __ptr_ = 0x0000000100208c08
      }
    }
  }
  [3] = {
    __cc = {
      first = "V3"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x00000001002086e8 strong=2 weak=1 {
        __ptr_ = 0x00000001002086e8
      }
    }
    __nc = {
      first = "V3"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x00000001002086e8 strong=2 weak=1 {
        __ptr_ = 0x00000001002086e8
      }
    }
  }
  [4] = {
    __cc = {
      first = "V1"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208ba8 strong=2 weak=1 {
        __ptr_ = 0x0000000100208ba8
      }
    }
    __nc = {
      first = "V1"
      second = std::__1::shared_ptr<Vertex<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::element_type @ 0x0000000100208ba8 strong=2 weak=1 {
        __ptr_ = 0x0000000100208ba8
      }
    }
  }
}
user1044328
  • 85
  • 1
  • 7
  • gdb is a great debugging tool, you can easily look up tutorials or read the documentation – Andria Apr 09 '17 at 02:02
  • My platform is Mac OS X and I use Xcode. Right now the default debugger is LLDB and it works very well for swift and Objective-C. I want to be able to debug C++ in it efficiently as well. So I kind of don't want to switch to GDB, unless that's the only way I can be productive. – user1044328 Apr 09 '17 at 02:08
  • 1
    Possible duplicate of [Printing/Debugging libc++ STL with XCode/LLDB](http://stackoverflow.com/questions/39680320/printing-debugging-libc-stl-with-xcode-lldb) – jtbandes Apr 09 '17 at 03:06
  • I already tried the suggestion in the link you posted @jtbandes – user1044328 Apr 09 '17 at 16:31
  • 1
    Can you post a complete example? It looks like the declaration line above got truncated, but you should be able to make this happen in a simple source file that you could show verbatim. It would also be helpful to see how you did the forward-declare the template class workaround. That has worked for me when I've tried it, but I have no doubt there are complexities in C++ that could defeat the workaround. Be good to see an example there as well. – Jim Ingham Apr 10 '17 at 18:48
  • @JimIngham I updated the description. I changes my code and choice of container. The problem however remains the same. – user1044328 Apr 12 '17 at 22:22

1 Answers1

0

I am pretty sure this is the same problem as described in the link jtbandes gave above. If I compile your example, then do:

> nm a.out | grep size 
> 

there are no matches, showing that no size function was generated. Note, since the compiler doesn't generally emit template function instantiations if the code doesn't use them you should actually call "size" somewhere to increase the chance it gets emitted. But even with that change, I still don't see this method generated. Rather the use is always inlined.

The debugger has very little chance of calling the inlined version of the function correctly. So there's not much it can do to help you here. There is a bug on clang & it's associated STL to be less aggressive about inlining at -O0. That's the only practical solution for this issue.

The workaround suggested in the linked problem was to forward declare the class. I didn't have any success coming up with a forward declaration of this class that passed the compiler, however. Maybe somebody with stronger C++-fu can?

print or frame variable can see the elements of the map and print its size, but that is done through a separate mechanism - the lldb "data formatters". If you want to know more about how that works, the reference is here:

http://lldb.llvm.org/varformats.html

Jim Ingham
  • 25,260
  • 2
  • 55
  • 63