-1

I am using the Google's C++ B-tree and I have an issue that someone might be able to answer.

First of all I get the following error:

In file included from ref_impl/../include/btree_map.h:31:0,
             from ref_impl/core.cpp:48:
ref_impl/../include/btree.h: In instantiation of ‘btree::btree_node<Params>::reference btree::btree_node<Params>::value(int) [with Params = btree::btree_map_params<unsigned int, unsigned int, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> >, 256>; btree::btree_node<Params>::reference = std::pair<const unsigned int, unsigned int>&]’:
ref_impl/../include/btree.h:809:33:   required from ‘btree::btree_iterator<Node, Reference, Pointer>::pointer btree::btree_iterator<Node, Reference, Pointer>::operator->() const [with Node = btree::btree_node<btree::btree_map_params<unsigned int, unsigned int, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> >, 256> >; Reference = std::pair<const unsigned int, unsigned int>&; Pointer = std::pair<const unsigned int, unsigned int>*; btree::btree_iterator<Node, Reference, Pointer>::pointer = std::pair<const unsigned int, unsigned int>*]’
ref_impl/core.cpp:539:18:   required from here 
ref_impl/../include/btree.h:557:57: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

btree.h:

pointer operator->() const {
    return &node->value(position);
 }

That seems to be the cause of the error.

Part of my code is the following:

auto range = duplicates.equal_range(query_ids_temp[i]);
    for (auto it = range.first; it != range.second; ++it) {
//error     
       std::vector<unsigned int>::iterator pos = std::find(deleted_queries.begin(), deleted_queries.end(), it->second);
    //error
        if (pos != deleted_queries.end()) {
            duplicates.erase(it);
            deleted_queries.erase(pos);

        } else {
            query_ids.push_back(it->second);
        }
    } 

The error seems to be the it->second

Additionally I tried:

for (btree_multimap<unsigned int, unsigned int>::iterator it = range.first; it != range.second; ++it) {
                    //error
        auto temp = it->second;
                    //error
        std::vector<unsigned int>::iterator position = std::find(deleted_queries.begin(), deleted_queries.end(), temp);
        if (position != deleted_queries.end()) {
            duplicates.erase(temp);
            deleted_queries.erase(position);

        } else {
            query_ids.push_back(it->second);
        }
    }

Please keep in mind that the error seems to be at auto temp = it->second;

I have also tried:

auto p = duplicates.find(query_ids_temp[i]);
      if(p != duplicates.end()) { // found a name
        do {
                    //error
            auto temp = p->second;
                    //error
            auto pos = std::find(deleted_queries.begin(), deleted_queries.end(), temp);
            if (pos != deleted_queries.end()) {
                duplicates.erase(p->second);
                deleted_queries.erase(pos);

            } else {
                query_ids.push_back(p->second);
            }

          p++;
        } while (p != duplicates.upper_bound(query_ids_temp[i]));
      }
      else{
        cout << "Name not found.\n";
      }

And the problem seem to be again the same: auto temp = p->second;

Any suggestions?

glarkou
  • 7,023
  • 12
  • 68
  • 118
  • 7
    You left out the important part of the error. Basically, the compiler said either "there was error XY in place Z" or "in place Z, there was error XY." You only posted "in place Z." And can you please mark the mentioned source line numbers in the code, e.g. using comments? – Angew is no longer proud of SO Mar 21 '13 at 12:43
  • Added comments can you please tell me if you need something more? – glarkou Mar 21 '13 at 12:48
  • 2
    You still haven't added the full error message. Please do so. – Angew is no longer proud of SO Mar 21 '13 at 12:56
  • 1
    Actually you haven't. The error message isn't complete. – Tony The Lion Mar 21 '13 at 12:59
  • Can you please point out what am I missing? – glarkou Mar 21 '13 at 13:03
  • @salamis: You only quoted the context part of the error message, not the actual error message. The error message is a line that includes the text "error:" Duh! – sellibitze Mar 21 '13 at 13:17
  • @sellibitze that's all from the compiler guys. Nothing more. – glarkou Mar 21 '13 at 13:23
  • 3
    BTW, this is not an error but a warning. If that's all the compiler said, it actually compiled your program successfully. But you should take this warning serious. You actually did not quote the relevant line from btree.h. It seems to be `reinterpret_cast(fields_.values[i]);` which looks very fishy. I suggest bugging the authors of this code with this issue. It looks like they violated the aliasing rules. – sellibitze Mar 21 '13 at 13:26
  • @sellibitze Thanks, yes the program runs but it returns wrong results thus I would have to wait. – glarkou Mar 21 '13 at 13:34
  • @sellibitze the reinterpret_cast could be avoided, at the cost of a construction of the pair instance being returned, as opposed to returning the pair stored internally by the btree. The cast is used to avoid that construction. – didierc Mar 22 '13 at 00:07
  • @didierc can you provide some sample code on how to achieve that? – glarkou Mar 22 '13 at 00:20
  • well, it's inside the btree class – didierc Mar 22 '13 at 00:22
  • As @sellibitze suggested, the best course of action is to discuss that matter with the library authors, they certainly know better than I do. – didierc Mar 22 '13 at 00:35
  • 1
    @salamis: Consider the possibility that this warning has nothing to do with your program generating the wrong output. If you're interested in solving this, please provide a http://sscce.org/ – sellibitze Mar 22 '13 at 12:56
  • @didierc: Yes. It seems they are using the cast just to turn the bytes of a mutable_value_type into an lvalue of type value_type. Since these types only differ in the const qualification of the member "first", I guess it's acceptable. – sellibitze Mar 22 '13 at 13:06
  • @sellibitze that was my understanding too. Thanks! – didierc Mar 22 '13 at 13:43

1 Answers1

1

The central caveat with Google's B-tree is that mutations invalidate iterators. The call to duplicates.erase() inside the loop invalidates "p".

The erase() method returns an iterator for this reason, so you can write something like:

if (...) {
  p = duplicates.erase(...);
  ...
} else {
  ...
  p++;
}

BTW, please provide details about which compiler version gives the warning.

Josh M.
  • 26
  • 2
  • Compiler version GCC 4.7.2 - Ubuntu 12.04. Is p->second the correct way to get the value? – glarkou Mar 25 '13 at 17:30
  • p->second is the value in the map, p->first is the key. I think you actually mean to write p = duplicates.erase(p); – Josh M. Mar 25 '13 at 17:39