Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

bug in VS2019 C++14 code optimization, or my fault?

I know that compiler is usually the last thing to blame for bugs in a code, but I do not see any other explanation for the following behaviour of the following C++ code (distilled down from an actual project):

#include <iostream>
#include <map>

int main()
{
    auto values = { 1, 3, 5 };
    std::map<int, int> valMap;

    for (auto const & val : values) {
        std::cout << "before assignment: valMap.size() = " << valMap.size();
        valMap[val] = valMap.size();
        std::cout << " -> set valMap[" << val << "] to " << valMap[val] << "\n";
    }
}

The expected output of this code is:

before assignment: valMap.size() = 0 -> set valMap[1] to 0
before assignment: valMap.size() = 1 -> set valMap[3] to 1
before assignment: valMap.size() = 2 -> set valMap[5] to 2

However, when I build a Release version with the (default) C++14 compiler, the output becomes:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

before assignment: valMap.size() = 0 -> set valMap[1] to 1
before assignment: valMap.size() = 1 -> set valMap[3] to 2
before assignment: valMap.size() = 2 -> set valMap[5] to 3

In other words, all values in valMap are larger by 1 than what they should be – it looks like the map gets appended before the right-hand-side of the assignment is evaluated.

This happens only in a Release build with C++14 language standard (which is the default in VS2019). Debug builds work fine (I hate when this happens – it took me hours to find out what is going on), as do Release builds of C++17 and C++20. This is why it looks like a bug to me.

My question is: is this a compiler bug, or am I doing something wrong/dangerous by using .size() in the assignment?

>Solution :

The evaluation order of A = B was not specified before c++17, after c++17 B is guaranteed to be evaluated before A, see https://en.cppreference.com/w/cpp/language/eval_order rule 20.

The behaviour of valMap[val] = valMap.size(); is therefore unspecified in c++14, you should use:

auto size = valMap.size();
valMap[val] = size;

Or avoid the problem by using emplace which is more explicit than relying on [] to automatically insert a value if it doesn’t already exist:

valMap.emplace(val, size);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading